use enum_dispatch::enum_dispatch;
use crate::character_class::CharacterClass;
use crate::op_atom::Atom;
use crate::op_back_reference::BackReference;
use crate::op_bol::Bol;
use crate::op_capture::Capture;
use crate::op_character_class::CharClass;
use crate::op_choice::Choice;
use crate::op_end_program::EndProgram;
use crate::op_eol::Eol;
use crate::op_greedy_fixed::GreedyFixed;
use crate::op_nothing::Nothing;
use crate::op_reluctant_fixed::ReluctantFixed;
use crate::op_repeat::Repeat;
use crate::op_sequence::Sequence;
use crate::op_unambiguous_repeat::UnambiguousRepeat;
use crate::re_flags::ReFlags;
use crate::re_matcher::ReMatcher;
pub(crate) const MATCHES_ZLS_AT_START: u32 = 1;
pub(crate) const MATCHES_ZLS_AT_END: u32 = 2;
pub(crate) const MATCHES_ZLS_ANYWHERE: u32 = 7;
pub(crate) const MATCHES_ZLS_NEVER: u32 = 1024;
#[enum_dispatch]
pub(crate) trait OperationControl {
fn get_match_length(&self) -> Option<usize> {
None
}
fn get_minimum_match_length(&self) -> usize {
self.get_match_length().unwrap_or(0)
}
fn get_initial_character_class(&self, _case_blind: bool) -> CharacterClass {
CharacterClass::all()
}
fn optimize(self, _flags: &ReFlags) -> Operation;
fn matches_empty_string(&self) -> u32;
fn matches_iter<'a>(
&'a self,
matcher: &'a ReMatcher<'a>,
position: usize,
) -> Box<dyn Iterator<Item = usize> + 'a>;
fn contains_capturing_expressions(&self) -> bool {
false
}
#[allow(dead_code)]
fn children(&self) -> Vec<Operation> {
Vec::new()
}
}
pub(crate) trait RepeatOperation {
fn child(&self) -> Operation;
fn min(&self) -> usize;
fn max(&self) -> usize;
fn greedy(&self) -> bool;
}
#[enum_dispatch(OperationControl)]
#[derive(Debug, Clone)]
pub(crate) enum Operation {
Bol,
Atom,
BackReference,
Capture,
Choice,
EndProgram,
Eol,
Nothing,
Repeat,
Sequence,
CharClass,
GreedyFixed,
ReluctantFixed,
UnambiguousRepeat,
}
impl Operation {
pub(crate) fn repeat_operation(&self) -> Option<&dyn RepeatOperation> {
match self {
Operation::Repeat(repeat) => Some(repeat),
Operation::GreedyFixed(greedy_fixed) => Some(greedy_fixed),
Operation::ReluctantFixed(reluctant_fixed) => Some(reluctant_fixed),
Operation::UnambiguousRepeat(unambiguous_repeat) => Some(unambiguous_repeat),
_ => None,
}
}
}
pub(crate) struct ForceProgressIterator<'a> {
base: Box<dyn Iterator<Item = usize> + 'a>,
count_zero_length: usize,
current_pos: Option<usize>,
}
impl<'a> ForceProgressIterator<'a> {
pub(crate) fn new(base: Box<dyn Iterator<Item = usize> + 'a>) -> Self {
Self {
base,
count_zero_length: 0,
current_pos: None,
}
}
}
impl Iterator for ForceProgressIterator<'_> {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
if self.count_zero_length > 3 {
return None;
}
let p = Some(self.base.next()?);
if p == self.current_pos {
self.count_zero_length += 1;
} else {
self.count_zero_length = 0;
self.current_pos = p;
}
p
}
}