///|
/// One validated batch input with a caller-controlled stable identifier.
pub struct BatchItem {
identifier_value : String
source_value : String
} derive(Eq, Debug)
///|
/// Per-item outcome; failures do not discard successful neighbors.
pub(all) enum BatchOutcome {
BatchSucceeded(ConversionResult)
BatchFailed(PinyinError)
} derive(Eq, Debug)
///|
/// One auditable batch output in the same position as its input.
pub struct BatchItemResult {
item_value : BatchItem
outcome_value : BatchOutcome
} derive(Eq, Debug)
///|
/// Aggregate conversion counts derived from item outcomes.
pub struct ConversionSummary {
total_value : Int
succeeded_value : Int
failed_value : Int
unknown_failure_value : Int
ambiguous_failure_value : Int
rendered_token_value : Int
diagnostic_value : Int
} derive(Eq, Debug)
///|
/// Ordered per-item outcomes plus a precomputed summary.
pub struct BatchResult {
item_values : Array[BatchItemResult]
summary_value : ConversionSummary
} derive(Eq, Debug)
///|
fn identifier_has_line_break(value : String) -> Bool {
for code in text_code_points(value) {
if code == 10 || code == 13 {
return true
}
}
false
}
///|
pub fn batch_item(
identifier : String,
source : String,
) -> Result[BatchItem, PinyinError] {
if identifier.length() == 0 {
return Err(InvalidBatchItem(identifier, "empty_identifier"))
}
if identifier_has_line_break(identifier) {
return Err(InvalidBatchItem(identifier, "line_break_in_identifier"))
}
Ok({ identifier_value: identifier, source_value: source })
}
///|
fn copy_batch_item_results(
values : Array[BatchItemResult],
) -> Array[BatchItemResult] {
let output : Array[BatchItemResult] = []
for value in values {
output.push(value)
}
output
}
///|
/// Converts all items without short-circuiting after an item failure.
pub fn convert_batch(
items : Array[BatchItem],
lexicon : Lexicon,
options : ConvertOptions,
) -> BatchResult {
let results : Array[BatchItemResult] = []
let mut succeeded = 0
let mut failed = 0
let mut unknown_failures = 0
let mut ambiguous_failures = 0
let mut rendered_tokens = 0
let mut diagnostics = 0
for item in items {
let outcome = match convert_text(item.source_value, lexicon, options) {
Ok(converted) => {
succeeded = succeeded + 1
rendered_tokens = rendered_tokens + converted.tokens().length()
diagnostics = diagnostics + converted.diagnostics().length()
BatchSucceeded(converted)
}
Err(error) => {
failed = failed + 1
match error {
UnknownCharacter(_) => unknown_failures = unknown_failures + 1
AmbiguousCharacter(_, _) =>
ambiguous_failures = ambiguous_failures + 1
_ => ()
}
BatchFailed(error)
}
}
results.push({ item_value: item, outcome_value: outcome })
}
{
item_values: results,
summary_value: {
total_value: items.length(),
succeeded_value: succeeded,
failed_value: failed,
unknown_failure_value: unknown_failures,
ambiguous_failure_value: ambiguous_failures,
rendered_token_value: rendered_tokens,
diagnostic_value: diagnostics,
},
}
}
///|
pub fn BatchItem::identifier(self : BatchItem) -> String {
self.identifier_value
}
///|
pub fn BatchItem::source(self : BatchItem) -> String {
self.source_value
}
///|
pub fn BatchItemResult::item(self : BatchItemResult) -> BatchItem {
self.item_value
}
///|
pub fn BatchItemResult::outcome(self : BatchItemResult) -> BatchOutcome {
self.outcome_value
}
///|
pub fn BatchItemResult::is_success(self : BatchItemResult) -> Bool {
self.outcome_value is BatchSucceeded(_)
}
///|
pub fn BatchItemResult::conversion(self : BatchItemResult) -> ConversionResult? {
match self.outcome_value {
BatchSucceeded(value) => Some(value)
BatchFailed(_) => None
}
}
///|
pub fn BatchItemResult::error(self : BatchItemResult) -> PinyinError? {
match self.outcome_value {
BatchSucceeded(_) => None
BatchFailed(error) => Some(error)
}
}
///|
pub fn BatchResult::items(self : BatchResult) -> Array[BatchItemResult] {
copy_batch_item_results(self.item_values)
}
///|
pub fn BatchResult::summary(self : BatchResult) -> ConversionSummary {
self.summary_value
}
///|
pub fn ConversionSummary::total(self : ConversionSummary) -> Int {
self.total_value
}
///|
pub fn ConversionSummary::succeeded(self : ConversionSummary) -> Int {
self.succeeded_value
}
///|
pub fn ConversionSummary::failed(self : ConversionSummary) -> Int {
self.failed_value
}
///|
pub fn ConversionSummary::unknown_failures(self : ConversionSummary) -> Int {
self.unknown_failure_value
}
///|
pub fn ConversionSummary::ambiguous_failures(self : ConversionSummary) -> Int {
self.ambiguous_failure_value
}
///|
pub fn ConversionSummary::rendered_tokens(self : ConversionSummary) -> Int {
self.rendered_token_value
}
///|
pub fn ConversionSummary::diagnostics(self : ConversionSummary) -> Int {
self.diagnostic_value
}