/// This mod is necessary until https://github.com/BurntSushi/fst/pull/137 gets merged. /// All credits for this code go to BurntSushi. use fst::Automaton; pub struct StartsWith(pub A); /// The `Automaton` state for `StartsWith`. pub struct StartsWithState(pub StartsWithStateKind); impl Clone for StartsWithState where A::State: Clone, { fn clone(&self) -> Self { Self(self.0.clone()) } } /// The inner state of a `StartsWithState`. pub enum StartsWithStateKind { /// Sink state that is reached when the automaton has matched the prefix. Done, /// State in which the automaton is while it hasn't matched the prefix. Running(A::State), } impl Clone for StartsWithStateKind where A::State: Clone, { fn clone(&self) -> Self { match self { StartsWithStateKind::Done => StartsWithStateKind::Done, StartsWithStateKind::Running(inner) => StartsWithStateKind::Running(inner.clone()), } } } impl Automaton for StartsWith { type State = StartsWithState; fn start(&self) -> StartsWithState { StartsWithState({ let inner = self.0.start(); if self.0.is_match(&inner) { StartsWithStateKind::Done } else { StartsWithStateKind::Running(inner) } }) } fn is_match(&self, state: &StartsWithState) -> bool { match state.0 { StartsWithStateKind::Done => true, StartsWithStateKind::Running(_) => false, } } fn can_match(&self, state: &StartsWithState) -> bool { match state.0 { StartsWithStateKind::Done => true, StartsWithStateKind::Running(ref inner) => self.0.can_match(inner), } } fn will_always_match(&self, state: &StartsWithState) -> bool { match state.0 { StartsWithStateKind::Done => true, StartsWithStateKind::Running(_) => false, } } fn accept(&self, state: &StartsWithState, byte: u8) -> StartsWithState { StartsWithState(match state.0 { StartsWithStateKind::Done => StartsWithStateKind::Done, StartsWithStateKind::Running(ref inner) => { let next_inner = self.0.accept(inner, byte); if self.0.is_match(&next_inner) { StartsWithStateKind::Done } else { StartsWithStateKind::Running(next_inner) } } }) } } /// An automaton that matches when one of its component automata match. #[derive(Clone, Debug)] pub struct Union(pub A, pub B); /// The `Automaton` state for `Union`. pub struct UnionState(pub A::State, pub B::State); impl Clone for UnionState where A::State: Clone, B::State: Clone, { fn clone(&self) -> Self { Self(self.0.clone(), self.1.clone()) } } impl Automaton for Union { type State = UnionState; fn start(&self) -> UnionState { UnionState(self.0.start(), self.1.start()) } fn is_match(&self, state: &UnionState) -> bool { self.0.is_match(&state.0) || self.1.is_match(&state.1) } fn can_match(&self, state: &UnionState) -> bool { self.0.can_match(&state.0) || self.1.can_match(&state.1) } fn will_always_match(&self, state: &UnionState) -> bool { self.0.will_always_match(&state.0) || self.1.will_always_match(&state.1) } fn accept(&self, state: &UnionState, byte: u8) -> UnionState { UnionState(self.0.accept(&state.0, byte), self.1.accept(&state.1, byte)) } } /// An automaton that matches when both of its component automata match. #[derive(Clone, Debug)] pub struct Intersection(pub A, pub B); /// The `Automaton` state for `Intersection`. pub struct IntersectionState(pub A::State, pub B::State); impl Clone for IntersectionState where A::State: Clone, B::State: Clone, { fn clone(&self) -> Self { Self(self.0.clone(), self.1.clone()) } } impl Automaton for Intersection { type State = IntersectionState; fn start(&self) -> IntersectionState { IntersectionState(self.0.start(), self.1.start()) } fn is_match(&self, state: &IntersectionState) -> bool { self.0.is_match(&state.0) && self.1.is_match(&state.1) } fn can_match(&self, state: &IntersectionState) -> bool { self.0.can_match(&state.0) && self.1.can_match(&state.1) } fn will_always_match(&self, state: &IntersectionState) -> bool { self.0.will_always_match(&state.0) && self.1.will_always_match(&state.1) } fn accept(&self, state: &IntersectionState, byte: u8) -> IntersectionState { IntersectionState(self.0.accept(&state.0, byte), self.1.accept(&state.1, byte)) } } /// An automaton that matches exactly when the automaton it wraps does not. #[derive(Clone, Debug)] pub struct Complement(pub A); /// The `Automaton` state for `Complement`. pub struct ComplementState(pub A::State); impl Clone for ComplementState where A::State: Clone, { fn clone(&self) -> Self { Self(self.0.clone()) } } impl Automaton for Complement { type State = ComplementState; fn start(&self) -> ComplementState { ComplementState(self.0.start()) } fn is_match(&self, state: &ComplementState) -> bool { !self.0.is_match(&state.0) } fn can_match(&self, state: &ComplementState) -> bool { !self.0.will_always_match(&state.0) } fn will_always_match(&self, state: &ComplementState) -> bool { !self.0.can_match(&state.0) } fn accept(&self, state: &ComplementState, byte: u8) -> ComplementState { ComplementState(self.0.accept(&state.0, byte)) } }