1use std::fmt::{Display, Formatter};
2use std::ops::Add;
3
4use regex::Error;
5
6use crate::{constants, solvers};
7
8#[cfg(feature = "re")]
9use regex::Regex;
10
11#[cfg(all(feature = "re-fancy", not(feature = "re")))]
12use fancy_regex::Regex;
13
14#[derive(Clone)]
16pub enum ReadableRe<'a> {
17 Digit,
19 Word,
21 Whitespace,
23 NonDigit,
25 NonWord,
27 NonWhitespace,
29 Boundary,
31
32 AsciiLetter,
34 AsciiNonLetter,
36 AsciiUppercase,
38 AsciiNonUppercase,
40 AsciiLowercase,
42 AsciiNonLowercase,
44 AsciiAlphanumeric,
46 AsciiNonAlphanumeric,
48 AsciiNumeric,
50 AsciiNonNumeric,
52
53 Hexadecimal,
55 NonHexadecimal,
57
58 Anything,
60 Everything,
62 SomethingGreedy,
64 Something,
66 AnyChar,
68
69 Period,
71 Caret,
73 Dollar,
75 Asterisk,
77 PlusSign,
79 MinusSign,
81 QuestionMark,
83 OpenBrace,
85 CloseBrace,
87 OpenBracket,
89 CloseBracket,
91 OpenParenthesis,
93 CloseParenthesis,
95 BackSlash,
97 Pipe,
99
100 Newline,
102 Tab,
104 Quote,
106 DoubleQuote,
108
109 #[cfg(feature = "re-fancy")]
110 Back1,
114 #[cfg(feature = "re-fancy")]
115 Back2,
119 #[cfg(feature = "re-fancy")]
120 Back3,
124 #[cfg(feature = "re-fancy")]
125 Back4,
129 #[cfg(feature = "re-fancy")]
130 Back5,
133 #[cfg(feature = "re-fancy")]
134 Back6,
138 #[cfg(feature = "re-fancy")]
139 Back7,
143 #[cfg(feature = "re-fancy")]
144 Back8,
148 #[cfg(feature = "re-fancy")]
149 Back9,
153
154 Raw(&'a str),
156 String(String),
158 Concat(solvers::Concat<'a>),
160
161 #[cfg(feature = "re-fancy")]
162 BackReference(solvers::BackReference),
166
167 Escape(solvers::Escape<'a>),
169 Group(solvers::Group<'a>),
171
172 #[cfg(feature = "re-fancy")]
173 PositiveLookAhead(solvers::PositiveLookAhead<'a>),
177 #[cfg(feature = "re-fancy")]
178 NegativeLookAhead(solvers::NegativeLookAhead<'a>),
182 #[cfg(feature = "re-fancy")]
183 PositiveLookBehind(solvers::PositiveLookBehind<'a>),
187 #[cfg(feature = "re-fancy")]
188 NegativeLookBehind(solvers::NegativeLookBehind<'a>),
192 NamedGroup(solvers::NamedGroup<'a>),
194 NonCaptureGroup(solvers::NonCaptureGroup<'a>),
196 Optional(solvers::Optional<'a>),
198 Either(solvers::Either<'a>),
200 Exactly(solvers::Exactly<'a>),
202 Ranged(solvers::Ranged<'a>),
204 ZeroOrMore(solvers::ZeroOrMore<'a>),
206 ZeroOrMoreLazy(solvers::ZeroOrMoreLazy<'a>),
208 OneOrMore(solvers::OneOrMore<'a>),
210 OneOrMoreLazy(solvers::OneOrMoreLazy<'a>),
212 StartsWith(solvers::StartsWith<'a>),
214 EndsWith(solvers::EndsWith<'a>),
216 StartsAndEndsWith(solvers::StartsAndEndsWith<'a>),
218 Chars(solvers::Chars),
220 NotChars(solvers::NotChars),
222 #[cfg(feature = "re-fancy")]
223 AtomicGroup(solvers::AtomicGroup<'a>),
226}
227
228impl Display for ReadableRe<'_> {
229 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
230 let to_write: &dyn Display = match self {
231 ReadableRe::Digit => &constants::DIGIT,
232 ReadableRe::Word => &constants::WORD,
233 ReadableRe::Whitespace => &constants::WHITESPACE,
234 ReadableRe::NonDigit => &constants::NON_DIGIT,
235 ReadableRe::NonWord => &constants::NON_WORD,
236 ReadableRe::NonWhitespace => &constants::NON_WHITESPACE,
237 ReadableRe::Boundary => &constants::BOUNDARY,
238 ReadableRe::AsciiLetter => &constants::ASCII_LETTER,
239 ReadableRe::AsciiNonLetter => &constants::ASCII_NON_LETTER,
240 ReadableRe::AsciiUppercase => &constants::ASCII_UPPERCASE,
241 ReadableRe::AsciiNonUppercase => &constants::ASCII_NON_UPPERCASE,
242 ReadableRe::AsciiLowercase => &constants::ASCII_LOWERCASE,
243 ReadableRe::AsciiNonLowercase => &constants::ASCII_NON_LOWERCASE,
244 ReadableRe::AsciiAlphanumeric => &constants::ASCII_ALPHANUMERIC,
245 ReadableRe::AsciiNonAlphanumeric => &constants::ASCII_NON_ALPHANUMERIC,
246 ReadableRe::AsciiNumeric => &constants::ASCII_NUMERIC,
247 ReadableRe::AsciiNonNumeric => &constants::ASCII_NON_NUMERIC,
248 ReadableRe::Hexadecimal => &constants::HEXADECIMAL,
249 ReadableRe::NonHexadecimal => &constants::NON_HEXADECIMAL,
250 ReadableRe::Anything => &constants::ANYTHING,
251 ReadableRe::Everything => &constants::EVERYTHING,
252 ReadableRe::SomethingGreedy => &constants::SOMETHING_GREEDY,
253 ReadableRe::Something => &constants::SOMETHING,
254 ReadableRe::AnyChar => &constants::ANY_CHAR,
255 ReadableRe::Period => &constants::PERIOD,
256 ReadableRe::Caret => &constants::CARET,
257 ReadableRe::Dollar => &constants::DOLLAR_SIGN,
258 ReadableRe::Asterisk => &constants::ASTERISK,
259 ReadableRe::PlusSign => &constants::PLUS_SIGN,
260 ReadableRe::MinusSign => &constants::MINUS_SIGN,
261 ReadableRe::QuestionMark => &constants::QUESTION_MARK,
262 ReadableRe::OpenBrace => &constants::OPEN_BRACE,
263 ReadableRe::CloseBrace => &constants::CLOSE_BRACE,
264 ReadableRe::OpenBracket => &constants::OPEN_BRACKET,
265 ReadableRe::CloseBracket => &constants::CLOSE_BRACKET,
266 ReadableRe::OpenParenthesis => &constants::OPEN_PARENTHESIS,
267 ReadableRe::CloseParenthesis => &constants::CLOSE_PARENTHESIS,
268 ReadableRe::BackSlash => &constants::BACKSLASH,
269 ReadableRe::Pipe => &constants::PIPE,
270 ReadableRe::Newline => &constants::NEWLINE,
271 ReadableRe::Tab => &constants::TAB,
272 ReadableRe::Quote => &constants::QUOTE,
273 ReadableRe::DoubleQuote => &constants::DOUBLE_QUOTE,
274 #[cfg(feature = "re-fancy")]
275 ReadableRe::Back1 => &constants::BACK_1,
276 #[cfg(feature = "re-fancy")]
277 ReadableRe::Back2 => &constants::BACK_2,
278 #[cfg(feature = "re-fancy")]
279 ReadableRe::Back3 => &constants::BACK_3,
280 #[cfg(feature = "re-fancy")]
281 ReadableRe::Back4 => &constants::BACK_4,
282 #[cfg(feature = "re-fancy")]
283 ReadableRe::Back5 => &constants::BACK_5,
284 #[cfg(feature = "re-fancy")]
285 ReadableRe::Back6 => &constants::BACK_6,
286 #[cfg(feature = "re-fancy")]
287 ReadableRe::Back7 => &constants::BACK_7,
288 #[cfg(feature = "re-fancy")]
289 ReadableRe::Back8 => &constants::BACK_8,
290 #[cfg(feature = "re-fancy")]
291 ReadableRe::Back9 => &constants::BACK_9,
292 ReadableRe::Raw(raw) => raw,
293 ReadableRe::String(s) => s,
294 ReadableRe::Concat(concat) => concat,
295 #[cfg(feature = "re-fancy")]
296 ReadableRe::BackReference(back_reference) => back_reference,
297 ReadableRe::Escape(scape) => scape,
298 ReadableRe::Group(group) => group,
299 #[cfg(feature = "re-fancy")]
300 ReadableRe::PositiveLookAhead(positive_look_ahead) => positive_look_ahead,
301 #[cfg(feature = "re-fancy")]
302 ReadableRe::NegativeLookAhead(negative_look_ahead) => negative_look_ahead,
303 #[cfg(feature = "re-fancy")]
304 ReadableRe::PositiveLookBehind(positive_look_behind) => positive_look_behind,
305 #[cfg(feature = "re-fancy")]
306 ReadableRe::NegativeLookBehind(negative_look_behind) => negative_look_behind,
307 ReadableRe::NamedGroup(named_group) => named_group,
308 ReadableRe::NonCaptureGroup(non_capture_group) => non_capture_group,
309 ReadableRe::Optional(optional) => optional,
310 ReadableRe::Either(either) => either,
311 ReadableRe::Exactly(exactly) => exactly,
312 ReadableRe::Ranged(between) => between,
313 ReadableRe::ZeroOrMore(zero_or_more) => zero_or_more,
314 ReadableRe::ZeroOrMoreLazy(zero_or_more_lazy) => zero_or_more_lazy,
315 ReadableRe::OneOrMore(one_or_more) => one_or_more,
316 ReadableRe::OneOrMoreLazy(one_or_more_lazy) => one_or_more_lazy,
317 ReadableRe::StartsWith(starts_with) => starts_with,
318 ReadableRe::EndsWith(ends_with) => ends_with,
319 ReadableRe::StartsAndEndsWith(starts_and_ends_with) => starts_and_ends_with,
320 ReadableRe::Chars(chars) => chars,
321 ReadableRe::NotChars(not_chars) => not_chars,
322 #[cfg(feature = "re-fancy")]
323 ReadableRe::AtomicGroup(atomic_group) => atomic_group,
324 };
325 write!(f, "{}", to_write)
326 }
327}
328
329impl<'a> ReadableRe<'a> {
330 pub fn compile(&self) -> Result<Regex, Error> {
331 Regex::new(&format!("{self}"))
332 }
333}
334
335impl<'a> Add<Self> for ReadableRe<'a> {
336 type Output = Self;
337
338 fn add(self, rhs: Self) -> Self::Output {
339 match (self, rhs) {
340 (Self::Concat(solvers::Concat(mut v1)), Self::Concat(solvers::Concat(v2))) => {
341 v1.extend(v2);
342 Self::Concat(solvers::Concat(v1))
343 }
344 (Self::Concat(solvers::Concat(mut v1)), other) => {
345 v1.push(other);
346 Self::Concat(solvers::Concat(v1))
347 }
348 (other, Self::Concat(solvers::Concat(v1))) => {
349 Self::Concat(solvers::Concat::new(std::iter::once(other).chain(v1)))
350 }
351 (re1, re2) => Self::Concat(solvers::Concat::new([re1, re2])),
352 }
353 }
354}
355
356impl<'a> From<&'a str> for ReadableRe<'a> {
357 fn from(s: &'a str) -> Self {
358 Self::Raw(s)
359 }
360}
361
362impl<'a> From<String> for ReadableRe<'a> {
363 fn from(s: String) -> Self {
364 Self::String(s)
365 }
366}