///|
fn classify_batch_failure(error : RomanReportError) -> BatchFailureKind {
match error {
EmptyRomanInput => EmptyInputFailure
UnsupportedRomanCharacter(_, _) => UnsupportedCharacterFailure
LowercaseRomanNotAllowed(_, _) => LowercaseNotAllowedFailure
InvalidRomanGrammar(_, code) => GrammarFailure(code)
NonCanonicalRoman(_) => NonCanonicalFailure
RomanReportOutOfRange(_) => OutOfRangeFailure
InvalidRomanConfiguration(_) => InvalidConfigurationFailure
}
}
///|
fn is_blank_batch_id(id : String) -> Bool {
let chars = id.to_array()
if chars.length() == 0 {
return true
}
for character in chars {
if !is_outer_whitespace(character) {
return false
}
}
true
}
///|
fn validate_batch_items(
items : Array[RomanBatchItem],
) -> Result[Unit, BatchValidationError] {
for index = 0; index < items.length(); index = index + 1 {
if is_blank_batch_id(items[index].id) {
return Err(EmptyBatchItemId(index))
}
for previous = 0; previous < index; previous = previous + 1 {
if items[previous].id == items[index].id {
return Err(DuplicateBatchItemId(items[index].id))
}
}
}
Ok(())
}
///|
fn increment_failure_count(
counts : Array[BatchFailureCount],
kind : BatchFailureKind,
) -> Unit {
for index = 0; index < counts.length(); index = index + 1 {
if counts[index].kind == kind {
counts[index] = { kind, count: counts[index].count + 1 }
return
}
}
counts.push({ kind, count: 1 })
}
///|
/// Parse an ID-addressed batch while retaining stable input order.
pub fn process_roman_batch(
items : Array[RomanBatchItem],
) -> Result[RomanBatchReport, BatchValidationError] {
match validate_batch_items(items) {
Err(error) => return Err(error)
Ok(_) => ()
}
let results : Array[RomanBatchResult] = []
let failure_counts : Array[BatchFailureCount] = []
let mut succeeded = 0
let mut failed = 0
let mut used_unicode_compatibility = 0
let mut trimmed_outer_whitespace = 0
for item in items {
match parse_with_config(item.input, item.config) {
Ok(report) => {
succeeded = succeeded + 1
if report.used_unicode_compatibility {
used_unicode_compatibility = used_unicode_compatibility + 1
}
if report.trimmed_outer_whitespace {
trimmed_outer_whitespace = trimmed_outer_whitespace + 1
}
results.push({
id: item.id,
input: item.input,
config: item.config,
outcome: BatchParsed(report),
})
}
Err(error) => {
failed = failed + 1
increment_failure_count(failure_counts, classify_batch_failure(error))
results.push({
id: item.id,
input: item.input,
config: item.config,
outcome: BatchFailed(error),
})
}
}
}
Ok({
results,
statistics: {
total: items.length(),
succeeded,
failed,
used_unicode_compatibility,
trimmed_outer_whitespace,
failure_counts,
},
})
}