use crate::algorithms::closure::ClosureType;
use crate::fst_properties::mutable_properties::closure_properties;
use crate::fst_properties::FstProperties;
use crate::fst_traits::MutableFst;
use crate::semirings::Semiring;
use crate::tr::Tr;
use crate::EPS_LABEL;
pub fn closure<W, F>(fst: &mut F, closure_type: ClosureType)
where
W: Semiring,
F: MutableFst<W>,
{
let props = fst.properties();
if let Some(start_state) = fst.start() {
let final_states_id: Vec<_> = fst
.final_states_iter()
.map(|s| {
(s, unsafe {
fst.final_weight_unchecked(s).unwrap_unchecked()
})
})
.collect();
for (final_state_id, final_weight) in final_states_id {
unsafe {
fst.add_tr_unchecked(
final_state_id,
Tr::new(EPS_LABEL, EPS_LABEL, final_weight, start_state),
)
};
}
}
if closure_type == ClosureType::ClosureStar {
let nstart = fst.add_state();
if let Some(start_state_id) = fst.start() {
unsafe {
fst.add_tr_unchecked(
nstart,
Tr::new(EPS_LABEL, EPS_LABEL, W::one(), start_state_id),
);
}
}
unsafe {
fst.set_start_unchecked(nstart);
fst.set_final_unchecked(nstart, W::one());
}
}
fst.set_properties_with_mask(
closure_properties(props, false),
FstProperties::all_properties(),
);
}