///|
/// Bounded candidate strings produced from recorded token readings.
pub struct VariantExpansion {
variant_values : Array[String]
truncated_value : Bool
} derive(Eq, Debug)
///|
fn append_unique_variant(values : Array[String], candidate : String) -> Unit {
for value in values {
if value == candidate {
return
}
}
values.push(candidate)
}
///|
fn token_variant_values(
token : ConvertedToken,
style : ToneStyle,
) -> Result[Array[String], PinyinError] {
if token.kind() == LiteralToken {
return Ok([token.rendered()])
}
let values : Array[String] = []
for candidate in token.candidates() {
let parsed = match parse_syllable(candidate) {
Err(error) => return Err(error)
Ok(value) => value
}
append_unique_variant(values, parsed.format(style, Lowercase))
}
if values.length() == 0 {
return Err(InvalidGeneratedData("pinyin_token_without_candidates"))
}
Ok(values)
}
///|
/// Expands recorded alternatives without performing contextual inference.
pub fn expand_conversion_variants(
result : ConversionResult,
style : ToneStyle,
separator : String,
limit : Int,
) -> Result[VariantExpansion, PinyinError] {
if limit <= 0 {
return Err(InvalidVariantLimit(limit))
}
if separator.length() == 0 {
return Err(InvalidSeparator("empty"))
}
let mut variants : Array[String] = [""]
let mut truncated = false
let mut previous_kind : TokenKind? = None
for token in result.tokens() {
let token_values = match token_variant_values(token, style) {
Err(error) => return Err(error)
Ok(values) => values
}
if variants.length() > limit / token_values.length() {
truncated = true
}
let next : Array[String] = []
for prefix in variants {
for value in token_values {
if next.length() >= limit {
truncated = true
break
}
let boundary = if previous_kind == Some(PinyinToken) &&
token.kind() == PinyinToken {
separator
} else {
""
}
append_unique_variant(next, prefix + boundary + value)
}
if next.length() >= limit {
break
}
}
variants = next
previous_kind = Some(token.kind())
}
Ok({ variant_values: variants, truncated_value: truncated })
}
///|
pub fn VariantExpansion::values(self : VariantExpansion) -> Array[String] {
self.variant_values.copy()
}
///|
pub fn VariantExpansion::generated(self : VariantExpansion) -> Int {
self.variant_values.length()
}
///|
pub fn VariantExpansion::truncated(self : VariantExpansion) -> Bool {
self.truncated_value
}