use arc::Arc;
use semirings::Semiring;
use std::fmt::Display;
use Result;
use StateId;
pub trait Fst:
CoreFst + PartialEq + Clone + for<'a> ArcIterator<'a> + for<'b> StateIterator<'b> + Display
{
}
pub trait CoreFst {
type W: Semiring;
fn start(&self) -> Option<StateId>;
fn final_weight(&self, &StateId) -> Option<<Self as CoreFst>::W>;
fn num_arcs(&self) -> usize;
fn is_final(&self, state_id: &StateId) -> bool {
self.final_weight(state_id).is_some()
}
}
pub trait StateIterator<'a> {
type Iter: Iterator<Item = StateId> + Clone;
fn states_iter(&'a self) -> Self::Iter;
}
pub trait ArcIterator<'a>: CoreFst
where
Self::W: 'a,
{
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() {
display_single_state!(self, &start_state, f);
for state_id in self.states_iter() {
if state_id != start_state {
display_single_state!(self, &state_id, f);
}
}
for final_state in self.final_states_iter() {
write!(
f,
"{}\t{}\n",
&final_state.state_id, &final_state.final_weight
);
}
}
Ok(())
}
}
};
}