litcheck_filecheck/pattern/search/
default.rs

1use 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}