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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
use arc::Arc;
use semirings::Semiring;
use std::fmt::Display;
use Result;
use StateId;
/// Trait defining the minimum interface necessary for a wFST
pub trait Fst:
CoreFst + PartialEq + Clone + for<'a> ArcIterator<'a> + for<'b> StateIterator<'b> + Display
{
}
/// Trait defining necessary methods for a wFST to access start states and final states
pub trait CoreFst {
/// Weight use in the wFST. This type must implement the Semiring trait
type W: Semiring;
/// Returns the ID of the start state of the wFST if it exists else none.
///
/// # Example
///
/// ```
/// use rustfst::fst_traits::{CoreFst, MutableFst};
/// use rustfst::fst_impls::VectorFst;
/// use rustfst::semirings::BooleanWeight;
///
/// // 1 - Create an FST
/// let mut fst = VectorFst::<BooleanWeight>::new();
/// let s = fst.add_state();
/// fst.set_start(&s);
///
/// // 2 - Access the start state
/// let start_state = fst.start();
/// assert_eq!(start_state, Some(s));
/// ```
fn start(&self) -> Option<StateId>;
/// Retrieves the final weight of a state (if the state is a final one).
///
/// # Example
///
/// ```
/// use rustfst::fst_traits::{CoreFst, MutableFst, ExpandedFst};
/// use rustfst::fst_impls::VectorFst;
/// use rustfst::semirings::{BooleanWeight, Semiring};
///
/// // 1 - Create an FST
/// let mut fst = VectorFst::<BooleanWeight>::new();
/// let s1 = fst.add_state();
/// let s2 = fst.add_state();
/// fst.set_final(&s2, BooleanWeight::one());
///
/// // 2 - Access the final weight of each state
/// assert_eq!(fst.final_weight(&s1), None);
/// assert_eq!(fst.final_weight(&s2), Some(BooleanWeight::one()));
/// ```
fn final_weight(&self, &StateId) -> Option<<Self as CoreFst>::W>;
/// Total number of arcs in the wFST. This is the sum of the outgoing arcs of each state.
///
/// # Example
///
/// ```
/// use rustfst::fst_traits::{CoreFst, MutableFst, ExpandedFst};
/// use rustfst::fst_impls::VectorFst;
/// use rustfst::semirings::{BooleanWeight, Semiring};
/// use rustfst::arc::Arc;
///
/// let mut fst = VectorFst::<BooleanWeight>::new();
/// let s1 = fst.add_state();
/// let s2 = fst.add_state();
///
/// assert_eq!(fst.num_arcs(), 0);
/// fst.add_arc(&s1, Arc::new(3, 5, BooleanWeight::new(true), s2));
/// assert_eq!(fst.num_arcs(), 1);
/// ```
fn num_arcs(&self) -> usize;
/// Returns whether or not the state with identifier passed as parameters is a final state.
///
/// # Example
///
/// ```
/// use rustfst::fst_traits::{CoreFst, MutableFst, ExpandedFst};
/// use rustfst::fst_impls::VectorFst;
/// use rustfst::semirings::{BooleanWeight, Semiring};
///
/// // 1 - Create an FST
/// let mut fst = VectorFst::<BooleanWeight>::new();
/// let s1 = fst.add_state();
/// let s2 = fst.add_state();
/// fst.set_final(&s2, BooleanWeight::one());
///
/// // 2 - Test if a state is final
/// assert!(!fst.is_final(&s1));
/// assert!(fst.is_final(&s2));
/// ```
fn is_final(&self, state_id: &StateId) -> bool {
self.final_weight(state_id).is_some()
}
//type Symtab: IntoIterator<Item=String>;
//fn get_isyms(&self) -> Option<Self::Symtab>;
//fn get_osyms(&self) -> Option<Self::Symtab>;
}
/// Trait to iterate over the states of a wFST
pub trait StateIterator<'a> {
/// Iterator used to iterate over the `state_id` of the states of an FST.
type Iter: Iterator<Item = StateId> + Clone;
/// Creates an iterator over the `state_id` of the states of an FST.
///
/// # Example
///
/// ```
/// use rustfst::fst_traits::{CoreFst, MutableFst, ExpandedFst, StateIterator};
/// use rustfst::fst_impls::VectorFst;
/// use rustfst::semirings::{BooleanWeight, Semiring};
///
/// let mut fst = VectorFst::<BooleanWeight>::new();
///
/// let s1 = fst.add_state();
/// let s2 = fst.add_state();
///
/// for state_id in fst.states_iter() {
/// println!("State ID : {:?}", state_id);
/// }
///
/// let states : Vec<_> = fst.states_iter().collect();
/// assert_eq!(states, vec![s1, s2]);
/// ```
fn states_iter(&'a self) -> Self::Iter;
}
/// Trait to iterate over the outgoing arcs of a partical state in a wFST
pub trait ArcIterator<'a>: CoreFst
where
Self::W: 'a,
{
/// Iterator used to iterate over the arcs leaving a state of an FST.
type Iter: Iterator<Item = &'a Arc<Self::W>> + Clone;
fn arcs_iter(&'a self, &StateId) -> Result<Self::Iter>;
}
macro_rules! add_or_fst {
($semiring:tt, $fst_type:ty) => {
impl<$semiring: 'static + Semiring> Add for $fst_type {
type Output = Result<$fst_type>;
fn add(self, rhs: $fst_type) -> Self::Output {
concat(&self, &rhs)
}
}
impl<$semiring: 'static + Semiring> BitOr for $fst_type {
type Output = Result<$fst_type>;
fn bitor(self, rhs: $fst_type) -> Self::Output {
union(&self, &rhs)
}
}
};
}
macro_rules! display_single_state {
($fst:expr, $state_id:expr, $f: expr) => {
for arc in $fst.arcs_iter($state_id).unwrap() {
write!(
$f,
"{}\t{}\t{}\t{}\t{}\n",
$state_id, &arc.nextstate, &arc.ilabel, &arc.olabel, &arc.weight
)?;
}
};
}
macro_rules! display_fst {
($semiring:tt, $fst_type:ty) => {
impl<$semiring: 'static + Semiring> fmt::Display for $fst_type
where
$semiring::Type: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(start_state) = self.start() {
// Firstly print the arcs leaving the start state
display_single_state!(self, &start_state, f);
// Secondly, print the arcs leaving all the other states
for state_id in self.states_iter() {
if state_id != start_state {
display_single_state!(self, &state_id, f);
}
}
// Finally, print the final states with their weight
for final_state in self.final_states_iter() {
write!(
f,
"{}\t{}\n",
&final_state.state_id, &final_state.final_weight
);
}
}
Ok(())
}
}
};
}