use crate::CompiledPat;
#[derive(Debug, Clone)]
pub struct MatchAny;
impl CompiledPat for MatchAny {
fn matches(&self, _: &str) -> bool {
true
}
}
#[derive(Debug, Clone)]
pub struct OptionalCharLen {
pub len: usize,
}
impl CompiledPat for OptionalCharLen {
fn matches(&self, string: &str) -> bool {
string.len() == self.len
}
}
#[derive(Debug, Clone)]
pub struct LiteralStr(pub String);
impl CompiledPat for LiteralStr {
fn matches(&self, string: &str) -> bool {
string == self.0
}
}
#[derive(Debug, Clone)]
pub struct General {
pub states: Vec<State>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum State {
Char(char),
Wildcard,
UnknownChar,
}
impl CompiledPat for General {
fn matches(&self, string: &str) -> bool {
let state_nr = self.states.len();
let mut active = vec![false; state_nr + 1].into_boxed_slice();
let mut active_next = vec![false; state_nr + 1].into_boxed_slice();
active[0] = true;
if self.states[0] == State::Wildcard {
active[1] = true;
}
for chr in string.chars() {
for j in 0..state_nr {
if active[j] {
let (stay, advance) = match self.states[j] {
State::Char(expected) => (false, chr == expected),
State::UnknownChar => (false, true),
State::Wildcard => (true, true),
};
active_next[j] |= stay;
active_next[j + 1] |= advance;
if j + 1 < state_nr && self.states[j + 1] == State::Wildcard {
active_next[j + 2] |= advance;
}
}
}
active.swap_with_slice(&mut active_next);
for j in 0..state_nr + 1 {
active_next[j] = false;
}
}
active[state_nr]
}
}