litcheck_filecheck/pattern/search/
default.rs1use crate::common::*;
2
3#[derive(Debug)]
4pub struct DefaultSearcher<I, M, E> {
5 input: I,
6 last_match_end: Option<usize>,
7 concrete: core::marker::PhantomData<(M, E)>,
8}
9impl<I, M, E> DefaultSearcher<I, M, E>
10where
11 I: super::Input,
12 M: super::Match,
13 E: std::error::Error,
14{
15 pub fn new(input: I) -> Self {
16 Self {
17 input,
18 last_match_end: None,
19 concrete: core::marker::PhantomData,
20 }
21 }
22}
23impl<I, M, E> Searcher for DefaultSearcher<I, M, E>
24where
25 I: super::Input,
26 M: super::Match,
27 E: std::error::Error,
28{
29 type Input = I;
30 type Match = M;
31 type MatchError = E;
32
33 fn input(&self) -> &Self::Input {
34 &self.input
35 }
36
37 fn last_match_end(&self) -> Option<usize> {
38 self.last_match_end
39 }
40
41 fn set_last_match_end(&mut self, start: usize) {
42 self.input.set_start(start);
43 self.last_match_end = Some(start);
44 }
45
46 fn set_range<R>(&mut self, range: R)
47 where
48 R: RangeBounds<usize>,
49 {
50 let fallback_bounds = self.input.range();
51 let range = range::range_from_bounds_with_defaults(
52 range,
53 fallback_bounds.start,
54 fallback_bounds.end,
55 );
56 self.input.set_range(range);
57 self.last_match_end = Some(range.start);
58 }
59
60 fn try_advance<F>(&mut self, mut finder: F) -> Result<Option<Self::Match>, Self::MatchError>
61 where
62 F: FnMut(&Self::Input) -> Result<Option<Self::Match>, Self::MatchError>,
63 {
64 let mut m = match finder(&self.input)? {
65 None => return Ok(None),
66 Some(m) => m,
67 };
68 if m.is_empty() && Some(m.end()) == self.last_match_end {
69 m = match self.handle_overlapping_empty_match(m, finder)? {
70 None => return Ok(None),
71 Some(m) => m,
72 };
73 }
74 self.input.set_start(m.end());
75 self.last_match_end = Some(m.end());
76 Ok(Some(m))
77 }
78
79 #[cold]
80 #[inline(never)]
81 fn handle_overlapping_empty_match<F>(
82 &mut self,
83 m: Self::Match,
84 mut finder: F,
85 ) -> Result<Option<Self::Match>, Self::MatchError>
86 where
87 F: FnMut(&Self::Input) -> Result<Option<Self::Match>, Self::MatchError>,
88 {
89 assert!(m.is_empty());
90 self.input
91 .set_start(self.input.start().checked_add(1).unwrap());
92 finder(&self.input)
93 }
94}