///|
fn find_state_pair(
pairs : Array[(Int32, Int32)],
sought : (Int32, Int32),
) -> Int32? {
for index in 0.. Result[Transducer[W], WfstError] {
if transducer_has_epsilon(left) || transducer_has_epsilon(right) {
return Err(WfstError::UnsupportedEpsilonComposition)
}
let left_start = match left.start {
Some(state) => state
None => return Err(WfstError::NoStartState)
}
let right_start = match right.start {
Some(state) => state
None => return Err(WfstError::NoStartState)
}
let builder = transducer_builder(left.semiring)
let pairs : Array[(Int32, Int32)] = []
pairs.push((left_start, right_start))
ignore(add_state(builder))
ignore(set_start(builder, 0))
let mut cursor = 0
while cursor < pairs.length() {
let (left_state, right_state) = pairs[cursor]
match (left.final_weights[left_state], right.final_weights[right_state]) {
(Some(left_weight), Some(right_weight)) =>
ignore(
set_final(
builder,
cursor,
semiring_times(left.semiring, left_weight, right_weight),
),
)
_ => ()
}
for left_arc in left.outgoing[left_state] {
for right_arc in right.outgoing[right_state] {
if left_arc.output == right_arc.input {
let destination_pair = (left_arc.destination, right_arc.destination)
let destination = match find_state_pair(pairs, destination_pair) {
Some(index) => index
None => {
let index = add_state(builder)
pairs.push(destination_pair)
index
}
}
ignore(
add_arc(
builder,
cursor,
left_arc.input,
right_arc.output,
destination,
semiring_times(left.semiring, left_arc.weight, right_arc.weight),
),
)
}
}
}
cursor = cursor + 1
}
Ok(build_transducer(builder))
}