ct_regex_internal/matcher/
quantifier.rs

1use std::{fmt::{self, Debug}, marker::PhantomData, vec};
2
3use crate::{expr::IndexedCaptures, haystack::{HaystackItem, HaystackOf}, matcher::{Matcher, Then}};
4
5#[derive(#[automatically_derived]
impl<I: ::core::default::Default + HaystackItem, A: ::core::default::Default +
    Matcher<I>, const N : usize> ::core::default::Default for
    QuantifierN<I, A, N> {
    #[inline]
    fn default() -> QuantifierN<I, A, N> {
        QuantifierN(::core::default::Default::default(),
            ::core::default::Default::default())
    }
}Default)]
6pub struct QuantifierN<I: HaystackItem, A: Matcher<I>, const N: usize>(
7    pub PhantomData<I>,
8    pub PhantomData<A>,
9);
10
11impl<I: HaystackItem, A: Matcher<I>, const N: usize> Matcher<I> for QuantifierN<I, A, N> {
12    fn matches<'a, H: HaystackOf<'a, I>>(hay: &mut H) -> bool {
13        let mut count = 0;
14        while A::matches(hay) {
15            count += 1;
16        }
17        count == N
18    }
19
20    fn captures<'a, H: HaystackOf<'a, I>>(hay: &mut H, caps: &mut IndexedCaptures) -> bool {
21        let mut count = 0;
22        while A::captures(hay, caps) {
23            count += 1;
24        }
25        count == N
26    }
27}
28
29impl<I: HaystackItem, A: Matcher<I>, const N: usize> Debug for QuantifierN<I, A, N> {
30    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31        f.write_fmt(format_args!("{0:?}{{{1}}}", A::default(), N))write!(f, "{:?}{{{N}}}", A::default())
32    }
33}
34
35#[derive(#[automatically_derived]
impl<I: ::core::default::Default + HaystackItem, A: ::core::default::Default +
    Matcher<I>, const N : usize> ::core::default::Default for
    QuantifierNOrMore<I, A, N> {
    #[inline]
    fn default() -> QuantifierNOrMore<I, A, N> {
        QuantifierNOrMore(::core::default::Default::default(),
            ::core::default::Default::default())
    }
}Default)]
36pub struct QuantifierNOrMore<I: HaystackItem, A: Matcher<I>, const N: usize>(
37    pub PhantomData<I>,
38    pub PhantomData<A>,
39);
40
41impl<I: HaystackItem, A: Matcher<I>, const N: usize> Matcher<I> for QuantifierNOrMore<I, A, N> {
42    fn matches<'a, H: HaystackOf<'a, I>>(hay: &mut H) -> bool {
43        let mut count = 0;
44        while A::matches(hay) {
45            count += 1;
46        }
47        count >= N
48    }
49
50    fn all_matches<'a, H: HaystackOf<'a, I>>(hay: &mut H) -> Vec<usize> {
51        let mut matches = ::alloc::vec::Vec::new()vec![];
52        let mut count = 0;
53
54        // Include zero-match position when N=0
55        if N == 0 {
56            matches.push(hay.index());
57        }
58
59        while A::matches(hay) {
60            count += 1;
61            if count >= N {
62                matches.push(hay.index());
63            }
64        }
65        matches
66    }
67
68    fn captures<'a, H: HaystackOf<'a, I>>(hay: &mut H, caps: &mut IndexedCaptures) -> bool {
69        let mut count = 0;
70        while A::captures(hay, caps) {
71            count += 1;
72        }
73        count >= N
74    }
75
76    fn all_captures<'a, H: HaystackOf<'a, I>>(
77        hay: &mut H,
78        caps: &mut IndexedCaptures
79    ) -> Vec<(usize, IndexedCaptures)> {
80        let mut captures = ::alloc::vec::Vec::new()vec![];
81        let mut count = 0;
82
83        // Include zero-match position when N=0
84        if N == 0 {
85            captures.push((hay.index(), caps.clone()));
86        }
87
88        while A::captures(hay, caps) {
89            count += 1;
90            if count >= N {
91                captures.push((hay.index(), caps.clone()));
92            }
93        }
94        captures
95    }
96}
97
98impl<I: HaystackItem, A: Matcher<I>, const N: usize> Debug for QuantifierNOrMore<I, A, N> {
99    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100        f.write_fmt(format_args!("{0:?}{{{1},}}", A::default(), N))write!(f, "{:?}{{{N},}}", A::default())
101    }
102}
103
104#[derive(#[automatically_derived]
impl<I: ::core::default::Default + HaystackItem, A: ::core::default::Default +
    Matcher<I>, const N : usize, const M : usize> ::core::default::Default for
    QuantifierNToM<I, A, N, M> {
    #[inline]
    fn default() -> QuantifierNToM<I, A, N, M> {
        QuantifierNToM(::core::default::Default::default(),
            ::core::default::Default::default())
    }
}Default)]
105pub struct QuantifierNToM<I: HaystackItem, A: Matcher<I>, const N: usize, const M: usize>(
106    pub PhantomData<I>,
107    pub PhantomData<A>,
108);
109
110impl<I: HaystackItem, A: Matcher<I>, const N: usize, const M: usize> Matcher<I> for QuantifierNToM<I, A, N, M> {
111    fn matches<'a, H: HaystackOf<'a, I>>(hay: &mut H) -> bool {
112        let mut count = 0;
113        while A::matches(hay) {
114            count += 1;
115
116            if count == M && count >= N {
117                return true;
118            }
119        }
120        N <= count && count <= M
121    }
122
123    fn all_matches<'a, H: HaystackOf<'a, I>>(hay: &mut H) -> Vec<usize> {
124        let mut matches = ::alloc::vec::Vec::new()vec![];
125        let mut count = 0;
126
127        // Include zero-match position when N=0
128        if N == 0 {
129            matches.push(hay.index());
130        }
131
132        while A::matches(hay) {
133            count += 1;
134            if N <= count && count <= M {
135                matches.push(hay.index());
136
137                if count == M {
138                    return matches;
139                }
140            }
141        }
142        matches
143    }
144
145    fn captures<'a, H: HaystackOf<'a, I>>(hay: &mut H, caps: &mut IndexedCaptures) -> bool {
146        let mut count = 0;
147        while A::captures(hay, caps) {
148            count += 1;
149
150            if count == M && count >= N {
151                return true;
152            }
153        }
154        N <= count && count <= M
155    }
156
157    fn all_captures<'a, H: HaystackOf<'a, I>>(
158        hay: &mut H,
159        caps: &mut IndexedCaptures
160    ) -> Vec<(usize, IndexedCaptures)> {
161        let mut captures = ::alloc::vec::Vec::new()vec![];
162        let mut count = 0;
163
164        // Include zero-match position when N=0
165        if N == 0 {
166            captures.push((hay.index(), caps.clone()));
167        }
168
169        while A::captures(hay, caps) {
170            count += 1;
171            if N <= count && count <= M {
172                captures.push((hay.index(), caps.clone()));
173
174                if count == M {
175                    return captures;
176                }
177            }
178        }
179        captures
180    }
181}
182
183impl<I: HaystackItem, A: Matcher<I>, const N: usize, const M: usize> Debug for QuantifierNToM<I, A, N, M> {
184    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185        f.write_fmt(format_args!("{0:?}{{{1},{2}}}", A::default(), N, M))write!(f, "{:?}{{{N},{M}}}", A::default())
186    }
187}
188
189#[derive(#[automatically_derived]
impl<I: ::core::default::Default + HaystackItem, Q: ::core::default::Default +
    Matcher<I>, T: ::core::default::Default + Matcher<I>>
    ::core::default::Default for QuantifierThen<I, Q, T> {
    #[inline]
    fn default() -> QuantifierThen<I, Q, T> {
        QuantifierThen(::core::default::Default::default(),
            ::core::default::Default::default(),
            ::core::default::Default::default())
    }
}Default)]
190pub struct QuantifierThen<I: HaystackItem, Q: Matcher<I>, T: Matcher<I>>(
191    pub PhantomData<I>,
192    pub PhantomData<Q>,
193    pub PhantomData<T>,
194);
195
196impl<I: HaystackItem, Q: Matcher<I>, T: Matcher<I>> Matcher<I> for QuantifierThen<I, Q, T> {
197    fn matches<'a, H: HaystackOf<'a, I>>(hay: &mut H) -> bool {
198        let mut rollback = hay.clone();
199        if Then::<I, Q, T>::matches(hay) {
200            true
201        } else {
202            // Try all valid match points for Q in reverse order (greedy).
203            let match_points = Q::all_matches(&mut rollback);
204
205            for point in match_points.into_iter().rev() {
206                // Overwrite the provided haystack with the progressed version.
207                hay.rollback(point);
208                if T::matches(hay) {
209                    return true;
210                }
211            }
212            false
213        }
214    }
215
216    fn all_matches<'a, H: HaystackOf<'a, I>>(hay: &mut H) -> Vec<usize> {
217        Then::<I, Q, T>::all_matches(hay)
218    }
219
220    fn captures<'a, H: HaystackOf<'a, I>>(hay: &mut H, caps: &mut IndexedCaptures) -> bool {
221        let mut rollback = (hay.clone(), caps.clone());
222        if Then::<I, Q, T>::captures(hay, caps) {
223            true
224        } else {
225            // Try all valid match points for Q in reverse order (greedy).
226            let match_points = Q::all_captures(&mut rollback.0, &mut rollback.1);
227
228            for (point_state, mut point_caps) in match_points.into_iter().rev() {
229                // Overwrite the provided haystack with the progressed version.
230                hay.rollback(point_state);
231                if T::captures(hay, &mut point_caps) {
232                    // Overwrite captures with the progressed version.
233                    *caps = point_caps;
234                    return true;
235                }
236            }
237            false
238        }
239    }
240
241    fn all_captures<'a, H: HaystackOf<'a, I>>(
242        hay: &mut H,
243        caps: &mut IndexedCaptures
244    ) -> Vec<(usize, IndexedCaptures)> {
245        Then::<I, Q, T>::all_captures(hay, caps)
246    }
247}
248
249impl<I: HaystackItem, Q: Matcher<I>, T: Matcher<I>> Debug for QuantifierThen<I, Q, T> {
250    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251        f.write_fmt(format_args!("{0:?}", Then::<I, Q, T>::default()))write!(f, "{:?}", Then::<I, Q, T>::default())
252    }
253}