1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use std::cmp::Ordering;

use crate::fst_properties::FstProperties;
use crate::fst_traits::MutableFst;
use crate::semirings::Semiring;
use crate::Tr;

pub trait TrCompare {
    fn compare<W: Semiring>(a: &Tr<W>, b: &Tr<W>) -> Ordering;
    fn properties(inprops: FstProperties) -> FstProperties;
}

/// Compare only input labels.
pub struct ILabelCompare {}

impl TrCompare for ILabelCompare {
    fn compare<W: Semiring>(a: &Tr<W>, b: &Tr<W>) -> Ordering {
        a.ilabel.cmp(&b.ilabel)
    }

    fn properties(inprops: FstProperties) -> FstProperties {
        let mut outprops =
            (inprops & FstProperties::arcsort_properties()) | FstProperties::I_LABEL_SORTED;
        if inprops.contains(FstProperties::ACCEPTOR) {
            outprops |= FstProperties::O_LABEL_SORTED;
        }
        outprops
    }
}

/// Compare only output labels.
pub struct OLabelCompare {}

impl TrCompare for OLabelCompare {
    fn compare<W: Semiring>(a: &Tr<W>, b: &Tr<W>) -> Ordering {
        a.olabel.cmp(&b.olabel)
    }

    fn properties(inprops: FstProperties) -> FstProperties {
        let mut outprops =
            (inprops & FstProperties::arcsort_properties()) | FstProperties::O_LABEL_SORTED;
        if inprops.contains(FstProperties::ACCEPTOR) {
            outprops |= FstProperties::I_LABEL_SORTED;
        }
        outprops
    }
}

/// Sorts trs leaving each state of the FST using a compare function
// The compare function could be passed only with the generic parameters but it seems less intuitive.
pub fn tr_sort<W, F, C>(fst: &mut F, _comp: C)
where
    W: Semiring,
    F: MutableFst<W>,
    C: TrCompare,
{
    let props = fst.properties();
    for state in 0..fst.num_states() {
        fst.sort_trs_unchecked(state, C::compare);
    }
    fst.set_properties_with_mask(C::properties(props), FstProperties::all_properties());
}