ct_regex_internal/matcher/
primitive.rs

1use std::fmt::{self, Debug};
2
3use crate::{expr::IndexedCaptures, haystack::{HaystackItem, HaystackOf}};
4
5pub trait Matcher<I: HaystackItem>: Debug + Default {
6    /// Checks if the start of the haystack contains a match for this [`Matcher`]. If this method
7    /// successfully matches the start of the haystack, `hay` is progressed so that `hay.item()`
8    /// hasn't been matched yet. On a fail, the state of hay is undefined.
9    fn matches<'a, H: HaystackOf<'a, I>>(hay: &mut H) -> bool;
10
11    // It would be nice to use a custom Iterator here rather than a Vec, but reversing an arbitrary
12    // match is not easy, so we just progress through linearly and store them all.
13    // This could cause issues with huge haystacks, but: all regexes need to be compiled at compile
14    // time and are hence controlled by the author. If their pattern will be operating on huge
15    // haystacks and need backtracking, that's up to them.
16
17    /// Produces a Vec of all valid haystack states produced as the result of a valid match at the
18    /// start of `hay`, used to implement backtracking. The Vec is produced in reverse priority
19    /// order, so the last match has the highest priority. After calling all_matches, the state of
20    /// `hay` itself is undefined.
21    ///
22    /// # Required
23    /// This method needs to be implemented by all [`Matcher`]s that can match more than one string
24    /// of characters from a haystack.
25    fn all_matches<'a, H: HaystackOf<'a, I>>(hay: &mut H) -> Vec<usize> {
26        if Self::matches(hay) {
27            <[_]>::into_vec(::alloc::boxed::box_new([hay.index()]))vec![hay.index()]
28        } else {
29            ::alloc::vec::Vec::new()vec![]
30        }
31    }
32
33    /// Checks if the start of the haystack contains a match for this Matcher, writing any groups
34    /// to `caps`. Similar to [`matches`], this method progresses `hay` and `caps` on a success. On
35    /// a fail, they have undefined states.
36    ///
37    /// # Required
38    /// This method needs to be implemented for capturing groups or any type that holds other
39    /// [`Matcher`]s, so that it can redirect to the relevant `capture` methods.
40    fn captures<'a, H: HaystackOf<'a, I>>(hay: &mut H, caps: &mut IndexedCaptures) -> bool {
41        let _ = caps;
42        Self::matches(hay)
43    }
44
45    /// Produces a Vec of all valid captures (and accompanying haystack states) present at the start
46    /// of `hay`. Used to implement backtracking for capturing methods. As with
47    /// [`all_matches`](Matcher::all_matches), the resulting Vec is produced in reverse priority
48    /// order. After calling all_captures, the state of `hay` and `caps` are undefined.
49    ///
50    /// # Required
51    /// This method needs to be implemented for any type that also implements
52    /// [`captures`](Matcher::captures) and [`all_matches`](Matcher::all_matches).
53    fn all_captures<'a, H: HaystackOf<'a, I>>(
54        hay: &mut H,
55        caps: &mut IndexedCaptures
56    ) -> Vec<(usize, IndexedCaptures)> {
57        if Self::captures(hay, caps) {
58            <[_]>::into_vec(::alloc::boxed::box_new([(hay.index(), caps.clone())]))vec![(hay.index(), caps.clone())]
59        } else {
60            ::alloc::vec::Vec::new()vec![]
61        }
62    }
63}
64
65#[derive(#[automatically_derived]
impl<const N : u8> ::core::default::Default for Byte<N> {
    #[inline]
    fn default() -> Byte<N> { Byte {} }
}Default)]
66pub struct Byte<const N: u8>;
67
68impl<const N: u8> Matcher<u8> for Byte<N> {
69    fn matches<'a, H: HaystackOf<'a, u8>>(hay: &mut H) -> bool {
70        if hay.item() == Some(N) {
71            hay.progress();
72            true
73        } else {
74            false
75        }
76    }
77}
78
79impl<const N: u8> Debug for Byte<N> {
80    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81        f.write_fmt(format_args!("{0:#04x}", N))write!(f, "{N:#04x}")
82    }
83}
84
85#[derive(#[automatically_derived]
impl<const A : u8, const B : u8> ::core::default::Default for ByteRange<A, B>
    {
    #[inline]
    fn default() -> ByteRange<A, B> { ByteRange {} }
}Default)]
86pub struct ByteRange<const A: u8, const B: u8>;
87
88impl<const A: u8, const B: u8> Matcher<u8> for ByteRange<A, B> {
89    fn matches<'a, H: HaystackOf<'a, u8>>(hay: &mut H) -> bool {
90        if let Some(byte) = hay.item() && A <= byte && byte <= B {
91            hay.progress();
92            true
93        } else {
94            false
95        }
96    }
97}
98
99impl<const A: u8, const B: u8> Debug for ByteRange<A, B> {
100    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101        f.write_fmt(format_args!("[{0:#04x}-{1:#04x}]", A, B))write!(f, "[{A:#04x}-{B:#04x}]")
102    }
103}
104
105#[derive(#[automatically_derived]
impl<const N : char> ::core::default::Default for Scalar<N> {
    #[inline]
    fn default() -> Scalar<N> { Scalar {} }
}Default)]
106pub struct Scalar<const N: char>;
107
108impl<const N: char> Matcher<char> for Scalar<N> {
109    fn matches<'a, H: HaystackOf<'a, char>>(hay: &mut H) -> bool {
110        if hay.item() == Some(N) {
111            hay.progress();
112            true
113        } else {
114            false
115        }
116    }
117}
118
119impl<const N: char> Debug for Scalar<N> {
120    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121        f.write_fmt(format_args!("{0}", N.escape_debug()))write!(f, "{}", N.escape_debug())
122    }
123}
124
125#[derive(#[automatically_derived]
impl<const A : char, const B : char> ::core::default::Default for
    ScalarRange<A, B> {
    #[inline]
    fn default() -> ScalarRange<A, B> { ScalarRange {} }
}Default)]
126pub struct ScalarRange<const A: char, const B: char>;
127
128impl<const A: char, const B: char> Matcher<char> for ScalarRange<A, B> {
129    fn matches<'a, H: HaystackOf<'a, char>>(hay: &mut H) -> bool {
130        if let Some(scalar) = hay.item() && A <= scalar && scalar <= B {
131            hay.progress();
132            true
133        } else {
134            false
135        }
136    }
137}
138
139impl<const A: char, const B: char> Debug for ScalarRange<A, B> {
140    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141        f.write_fmt(format_args!("[{0}-{1}]", A.escape_debug(), B.escape_debug()))write!(f, "[{}-{}]", A.escape_debug(), B.escape_debug())
142    }
143}
144
145#[derive(#[automatically_derived]
impl ::core::default::Default for Always {
    #[inline]
    fn default() -> Always { Always {} }
}Default)]
146pub struct Always;
147
148impl<I: HaystackItem> Matcher<I> for Always {
149    fn matches<'a, H: HaystackOf<'a, I>>(_hay: &mut H) -> bool {
150        true
151    }
152}
153
154impl Debug for Always {
155    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156        f.write_fmt(format_args!("()"))write!(f, "()")
157    }
158}
159
160#[derive(#[automatically_derived]
impl ::core::default::Default for Beginning {
    #[inline]
    fn default() -> Beginning { Beginning {} }
}Default)]
161pub struct Beginning;
162
163impl<I: HaystackItem> Matcher<I> for Beginning {
164    fn matches<'a, H: HaystackOf<'a, I>>(hay: &mut H) -> bool {
165        hay.is_start()
166    }
167}
168
169impl Debug for Beginning {
170    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
171        f.write_fmt(format_args!("^"))write!(f, "^")
172    }
173}
174
175#[derive(#[automatically_derived]
impl ::core::default::Default for End {
    #[inline]
    fn default() -> End { End {} }
}Default)]
176pub struct End;
177
178impl<I: HaystackItem> Matcher<I> for End {
179    fn matches<'a, H: HaystackOf<'a, I>>(hay: &mut H) -> bool {
180        hay.is_end()
181    }
182}
183
184impl Debug for End {
185    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186        f.write_fmt(format_args!("$"))write!(f, "$")
187    }
188}