1use crate::bytes::MatchBytes;
2use crate::Match;
3use alloc::string::String;
4use core::ops::Range;
5
6pub(crate) fn next_input_pos(text: &[u8], i: usize) -> usize {
11 let b = match text.get(i) {
12 None => return i + 1,
13 Some(&b) => b,
14 };
15 i + crate::codepoint_len(b)
16}
17
18#[derive(Debug)]
25pub struct RegexInput<'h, S: Input + ?Sized> {
26 haystack: &'h S,
27 start: usize,
28 range: Range<usize>,
29 anchored: bool,
30 start_text: Option<bool>,
31 end_text: Option<bool>,
32 continue_from_previous_match_end: Option<bool>,
33}
34
35impl<'h, S: Input + ?Sized> Clone for RegexInput<'h, S> {
36 fn clone(&self) -> Self {
39 Self {
40 haystack: self.haystack,
41 start: self.start,
42 range: self.range.clone(),
43 anchored: self.anchored,
44 start_text: self.start_text,
45 end_text: self.end_text,
46 continue_from_previous_match_end: self.continue_from_previous_match_end,
47 }
48 }
49}
50
51impl<'h, S: Input + ?Sized> RegexInput<'h, S> {
52 pub fn new(haystack: &'h S) -> Self {
54 Self {
55 haystack,
56 start: 0,
57 range: 0..haystack.len(),
58 anchored: false,
59 start_text: None,
60 end_text: None,
61 continue_from_previous_match_end: None,
62 }
63 }
64
65 pub fn haystack(&self) -> &'h S {
67 self.haystack
68 }
69
70 pub fn start(&self) -> usize {
72 self.start
73 }
74
75 pub fn get_range(&self) -> Range<usize> {
77 self.range.clone()
78 }
79
80 pub fn from_pos(mut self, start: usize) -> Self {
82 self.start = start;
83 self
84 }
85
86 pub fn range(mut self, range: Range<usize>) -> Self {
93 assert!(range.start <= range.end, "range start must be <= range end");
94 assert!(
95 range.end <= self.haystack.len(),
96 "range end must be within haystack bounds"
97 );
98 self.range = range;
99 self
100 }
101
102 pub fn start_text(mut self, yes: bool) -> Self {
108 self.start_text = if yes { None } else { Some(false) };
109 self
110 }
111
112 pub fn end_text(mut self, yes: bool) -> Self {
118 self.end_text = if yes { None } else { Some(false) };
119 self
120 }
121
122 pub fn continue_from_previous_match_end(mut self, yes: bool) -> Self {
128 self.continue_from_previous_match_end = if yes { None } else { Some(false) };
129 self
130 }
131
132 pub fn anchored(mut self, yes: bool) -> Self {
139 self.anchored = yes;
140 self
141 }
142
143 pub(crate) fn effective_start(&self) -> usize {
144 self.start.max(self.range.start)
145 }
146
147 pub(crate) fn is_done(&self) -> bool {
148 self.effective_start() > self.range.end
149 }
150
151 pub(crate) fn set_start(&mut self, start: usize) {
152 self.start = start;
153 }
154
155 pub(crate) fn start_text_override(&self) -> Option<bool> {
156 self.start_text
157 }
158
159 pub(crate) fn end_text_override(&self) -> Option<bool> {
160 self.end_text
161 }
162
163 pub(crate) fn continue_from_previous_match_end_override(&self) -> Option<bool> {
164 self.continue_from_previous_match_end
165 }
166
167 pub(crate) fn is_anchored(&self) -> bool {
168 self.anchored
169 }
170}
171
172impl<'h, S: Input + ?Sized> From<&'h S> for RegexInput<'h, S> {
173 fn from(haystack: &'h S) -> Self {
174 Self::new(haystack)
175 }
176}
177
178pub trait Input {
191 type Match<'t>
193 where
194 Self: 't;
195
196 fn len(&self) -> usize;
198 fn as_bytes(&self) -> &[u8];
200 fn is_char_boundary(&self, ix: usize) -> bool;
202 fn is_ascii(&self) -> bool;
204 fn prev_codepoint_ix(&self, i: usize) -> usize;
206 fn is_empty(&self) -> bool {
208 self.len() == 0
209 }
210 fn make_match<'t>(&'t self, start: usize, end: usize) -> Self::Match<'t>;
212 fn advance_position(&self, i: usize) -> usize;
214}
215
216impl<S: Input + ?Sized> Input for &S {
217 type Match<'t>
218 = S::Match<'t>
219 where
220 Self: 't;
221
222 fn len(&self) -> usize {
223 (**self).len()
224 }
225 fn as_bytes(&self) -> &[u8] {
226 (**self).as_bytes()
227 }
228 fn is_char_boundary(&self, ix: usize) -> bool {
229 (**self).is_char_boundary(ix)
230 }
231 fn is_ascii(&self) -> bool {
232 (**self).is_ascii()
233 }
234 fn prev_codepoint_ix(&self, i: usize) -> usize {
235 (**self).prev_codepoint_ix(i)
236 }
237 fn make_match<'t>(&'t self, start: usize, end: usize) -> Self::Match<'t> {
238 (**self).make_match(start, end)
239 }
240 fn advance_position(&self, i: usize) -> usize {
241 (**self).advance_position(i)
242 }
243}
244
245impl Input for str {
246 type Match<'t> = Match<'t>;
247
248 fn len(&self) -> usize {
249 str::len(self)
250 }
251 fn as_bytes(&self) -> &[u8] {
252 str::as_bytes(self)
253 }
254 fn is_char_boundary(&self, ix: usize) -> bool {
255 str::is_char_boundary(self, ix)
256 }
257 fn is_ascii(&self) -> bool {
258 str::is_ascii(self)
259 }
260 fn prev_codepoint_ix(&self, i: usize) -> usize {
261 crate::prev_codepoint_ix(self, i)
262 }
263 fn make_match<'t>(&'t self, start: usize, end: usize) -> Match<'t> {
264 Match::new(self, start, end)
265 }
266 fn advance_position(&self, i: usize) -> usize {
267 next_input_pos(self.as_bytes(), i)
268 }
269}
270
271impl Input for String {
272 type Match<'t> = Match<'t>;
273
274 fn len(&self) -> usize {
275 String::len(self)
276 }
277 fn as_bytes(&self) -> &[u8] {
278 String::as_bytes(self)
279 }
280 fn is_char_boundary(&self, ix: usize) -> bool {
281 str::is_char_boundary(self, ix)
282 }
283 fn is_ascii(&self) -> bool {
284 str::is_ascii(self)
285 }
286 fn prev_codepoint_ix(&self, i: usize) -> usize {
287 crate::prev_codepoint_ix(self, i)
288 }
289 fn make_match<'t>(&'t self, start: usize, end: usize) -> Match<'t> {
290 Match::new(self, start, end)
291 }
292 fn advance_position(&self, i: usize) -> usize {
293 next_input_pos(self.as_bytes(), i)
294 }
295}
296
297impl Input for [u8] {
298 type Match<'t> = MatchBytes<'t>;
299
300 fn len(&self) -> usize {
301 <[u8]>::len(self)
302 }
303 fn as_bytes(&self) -> &[u8] {
304 self
305 }
306 fn is_char_boundary(&self, ix: usize) -> bool {
307 ix == 0 || ix >= <[u8]>::len(self) || self[ix] & 0xC0 != 0x80
308 }
309 fn is_ascii(&self) -> bool {
310 <[u8]>::is_ascii(self)
311 }
312 fn prev_codepoint_ix(&self, mut i: usize) -> usize {
313 i -= 1;
314 while i > 0 && self[i] & 0xC0 == 0x80 {
315 i -= 1;
316 }
317 i
318 }
319 fn make_match<'t>(&'t self, start: usize, end: usize) -> MatchBytes<'t> {
320 MatchBytes::new(self, start, end)
321 }
322 fn advance_position(&self, i: usize) -> usize {
323 i + 1
324 }
325}
326
327impl<const N: usize> Input for [u8; N] {
328 type Match<'t> = MatchBytes<'t>;
329
330 fn len(&self) -> usize {
331 N
332 }
333 fn as_bytes(&self) -> &[u8] {
334 self
335 }
336 fn is_char_boundary(&self, ix: usize) -> bool {
337 ix == 0 || ix >= N || self[ix] & 0xC0 != 0x80
338 }
339 fn is_ascii(&self) -> bool {
340 <[u8]>::is_ascii(self)
341 }
342 fn prev_codepoint_ix(&self, mut i: usize) -> usize {
343 i -= 1;
344 while i > 0 && self[i] & 0xC0 == 0x80 {
345 i -= 1;
346 }
347 i
348 }
349 fn make_match<'t>(&'t self, start: usize, end: usize) -> MatchBytes<'t> {
350 MatchBytes::new(self, start, end)
351 }
352 fn advance_position(&self, i: usize) -> usize {
353 i + 1
354 }
355}