Skip to main content

rgx/engine/
mod.rs

1pub mod fancy;
2#[cfg(feature = "pcre2-engine")]
3pub mod pcre2;
4pub mod rust_regex;
5
6use std::fmt;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum EngineKind {
10    RustRegex,
11    FancyRegex,
12    #[cfg(feature = "pcre2-engine")]
13    Pcre2,
14}
15
16impl EngineKind {
17    pub fn all() -> Vec<EngineKind> {
18        vec![
19            EngineKind::RustRegex,
20            EngineKind::FancyRegex,
21            #[cfg(feature = "pcre2-engine")]
22            EngineKind::Pcre2,
23        ]
24    }
25
26    pub fn next(self) -> EngineKind {
27        match self {
28            EngineKind::RustRegex => EngineKind::FancyRegex,
29            #[cfg(feature = "pcre2-engine")]
30            EngineKind::FancyRegex => EngineKind::Pcre2,
31            #[cfg(not(feature = "pcre2-engine"))]
32            EngineKind::FancyRegex => EngineKind::RustRegex,
33            #[cfg(feature = "pcre2-engine")]
34            EngineKind::Pcre2 => EngineKind::RustRegex,
35        }
36    }
37}
38
39impl fmt::Display for EngineKind {
40    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41        match self {
42            EngineKind::RustRegex => write!(f, "Rust regex"),
43            EngineKind::FancyRegex => write!(f, "fancy-regex"),
44            #[cfg(feature = "pcre2-engine")]
45            EngineKind::Pcre2 => write!(f, "PCRE2"),
46        }
47    }
48}
49
50#[derive(Debug, Clone, Default)]
51pub struct EngineFlags {
52    pub case_insensitive: bool,
53    pub multi_line: bool,
54    pub dot_matches_newline: bool,
55    pub unicode: bool,
56    pub extended: bool,
57}
58
59impl EngineFlags {
60    pub fn toggle_case_insensitive(&mut self) {
61        self.case_insensitive = !self.case_insensitive;
62    }
63    pub fn toggle_multi_line(&mut self) {
64        self.multi_line = !self.multi_line;
65    }
66    pub fn toggle_dot_matches_newline(&mut self) {
67        self.dot_matches_newline = !self.dot_matches_newline;
68    }
69    pub fn toggle_unicode(&mut self) {
70        self.unicode = !self.unicode;
71    }
72    pub fn toggle_extended(&mut self) {
73        self.extended = !self.extended;
74    }
75}
76
77#[derive(Debug, Clone)]
78pub struct Match {
79    pub start: usize,
80    pub end: usize,
81    pub text: String,
82    pub captures: Vec<CaptureGroup>,
83}
84
85#[derive(Debug, Clone)]
86pub struct CaptureGroup {
87    pub index: usize,
88    pub name: Option<String>,
89    pub start: usize,
90    pub end: usize,
91    pub text: String,
92}
93
94#[derive(Debug)]
95pub enum EngineError {
96    CompileError(String),
97    MatchError(String),
98}
99
100impl fmt::Display for EngineError {
101    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102        match self {
103            EngineError::CompileError(msg) => write!(f, "Compile error: {msg}"),
104            EngineError::MatchError(msg) => write!(f, "Match error: {msg}"),
105        }
106    }
107}
108
109impl std::error::Error for EngineError {}
110
111pub type EngineResult<T> = Result<T, EngineError>;
112
113pub trait RegexEngine: Send + Sync {
114    fn kind(&self) -> EngineKind;
115    fn compile(&self, pattern: &str, flags: &EngineFlags) -> EngineResult<Box<dyn CompiledRegex>>;
116}
117
118pub trait CompiledRegex: Send + Sync {
119    fn find_matches(&self, text: &str) -> EngineResult<Vec<Match>>;
120}
121
122pub fn create_engine(kind: EngineKind) -> Box<dyn RegexEngine> {
123    match kind {
124        EngineKind::RustRegex => Box::new(rust_regex::RustRegexEngine),
125        EngineKind::FancyRegex => Box::new(fancy::FancyRegexEngine),
126        #[cfg(feature = "pcre2-engine")]
127        EngineKind::Pcre2 => Box::new(pcre2::Pcre2Engine),
128    }
129}