/// 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))
}
}