rustfst/algorithms/
fst_convert.rs

1use crate::fst_traits::{AllocableFst, ExpandedFst, Fst, MutableFst};
2use crate::semirings::Semiring;
3use crate::Trs;
4
5/// Generic method to convert an Fst into any other types implementing the MutableFst trait.
6pub fn fst_convert_from_ref<W, F1, F2>(ifst: &F1) -> F2
7where
8    W: Semiring,
9    F1: Fst<W>,
10    F2: MutableFst<W> + AllocableFst<W>,
11{
12    let mut ofst = F2::new();
13
14    // TODO: If ExpandedFst is implemented, use fst.num_states()
15    ofst.add_states(ifst.states_iter().count());
16
17    if let Some(start) = ifst.start() {
18        unsafe { ofst.set_start_unchecked(start) };
19
20        for data in ifst.fst_iter() {
21            unsafe {
22                ofst.reserve_trs_unchecked(data.state_id, data.num_trs);
23            }
24            for tr in data.trs.trs() {
25                unsafe { ofst.add_tr_unchecked(data.state_id, tr.clone()) };
26            }
27
28            if let Some(final_weight) = data.final_weight {
29                unsafe { ofst.set_final_unchecked(data.state_id, final_weight.clone()) };
30            }
31        }
32    }
33
34    ofst.set_symts_from_fst(ifst);
35    ofst.set_properties_with_mask(ifst.properties(), ifst.properties());
36
37    ofst
38}
39
40/// Generic method to convert an Fst into any other types implementing the MutableFst trait.
41pub fn fst_convert<W, F1, F2>(ifst: F1) -> F2
42where
43    W: Semiring,
44    F1: ExpandedFst<W>,
45    F2: MutableFst<W> + AllocableFst<W>,
46{
47    let mut ofst = F2::new();
48    ofst.add_states(ifst.num_states());
49
50    ofst.set_symts_from_fst(&ifst);
51    let iprops = ifst.properties();
52
53    if let Some(start) = ifst.start() {
54        unsafe { ofst.set_start_unchecked(start) };
55
56        for fst_iter_data in ifst.fst_into_iter() {
57            unsafe {
58                ofst.reserve_trs_unchecked(fst_iter_data.state_id, fst_iter_data.num_trs);
59            }
60            for tr in fst_iter_data.trs {
61                unsafe { ofst.add_tr_unchecked(fst_iter_data.state_id, tr) }
62            }
63
64            if let Some(w) = fst_iter_data.final_weight {
65                unsafe { ofst.set_final_unchecked(fst_iter_data.state_id, w) };
66            }
67        }
68    }
69
70    ofst.set_properties_with_mask(iprops, iprops);
71
72    ofst
73}