Skip to main content

litcheck_filecheck/pattern/search/
mod.rs

1mod aho_corasick;
2mod r#default;
3mod pattern_set;
4mod regex;
5mod substring_set;
6
7pub use self::aho_corasick::AhoCorasickSearcher;
8pub use self::r#default::DefaultSearcher;
9pub use self::pattern_set::PatternSetSearcher;
10pub use self::regex::RegexSearcher;
11pub use self::substring_set::SubstringSetSearcher;
12pub use crate::pattern::matcher::RegexSetSearcher;
13
14use std::{fmt, ops::RangeBounds};
15
16use crate::common::{
17    Context, DiagResult, MatchResult, PatternIdentifier, Range, SourceId, SourceSpan,
18};
19
20pub trait Searcher {
21    type Input: Input;
22    type Match: Match;
23    type MatchError: std::error::Error;
24
25    fn input(&self) -> &Self::Input;
26    fn last_match_end(&self) -> Option<usize>;
27    fn set_last_match_end(&mut self, end: usize);
28    fn set_range<R>(&mut self, range: R)
29    where
30        R: RangeBounds<usize>;
31    fn advance<F>(&mut self, finder: F) -> Option<Self::Match>
32    where
33        F: FnMut(&Self::Input) -> Result<Option<Self::Match>, Self::MatchError>,
34    {
35        match self.try_advance(finder) {
36            Ok(m) => m,
37            Err(err) => panic!("unexpected search error: {}", err),
38        }
39    }
40    fn try_advance<F>(&mut self, finder: F) -> Result<Option<Self::Match>, Self::MatchError>
41    where
42        F: FnMut(&Self::Input) -> Result<Option<Self::Match>, Self::MatchError>;
43
44    fn handle_overlapping_empty_match<F>(
45        &mut self,
46        m: Self::Match,
47        finder: F,
48    ) -> Result<Option<Self::Match>, Self::MatchError>
49    where
50        F: FnMut(&Self::Input) -> Result<Option<Self::Match>, Self::MatchError>;
51}
52
53pub trait PatternSearcher<'input> {
54    type Input: Input;
55    type PatternID: PatternIdentifier;
56
57    fn input(&self) -> &Self::Input;
58    fn last_match_end(&self) -> Option<usize>;
59    fn set_last_match_end(&mut self, end: usize);
60    fn patterns_len(&self) -> usize;
61    fn pattern_span(&self, id: Self::PatternID) -> SourceSpan;
62    fn try_match_next<'context, C>(&mut self, context: &mut C) -> DiagResult<MatchResult<'input>>
63    where
64        C: Context<'input, 'context> + ?Sized;
65}
66
67pub trait Match: fmt::Debug {
68    type PatternID: PatternIdentifier;
69
70    fn is_empty(&self) -> bool;
71    fn pattern(&self) -> Self::PatternID;
72    fn end(&self) -> usize;
73    fn range(&self) -> Range<usize>;
74}
75
76pub trait Input: fmt::Debug {
77    fn source_id(&self) -> SourceId;
78    fn buffer(&self) -> &[u8];
79    fn anchored(&self) -> bool;
80    fn range(&self) -> Range<usize>;
81    fn start(&self) -> usize;
82    fn set_start(&mut self, start: usize);
83    fn set_range(&mut self, range: Range<usize>);
84    fn as_input(&self) -> crate::common::Input<'_> {
85        crate::common::Input::new(self.source_id(), self.buffer(), false)
86            .anchored(self.anchored())
87            .bounded(self.range())
88    }
89}
90
91impl<'a> Input for crate::common::Input<'a> {
92    #[inline(always)]
93    fn source_id(&self) -> SourceId {
94        crate::common::Input::source_id(self)
95    }
96    #[inline(always)]
97    fn buffer(&self) -> &[u8] {
98        crate::common::Input::buffer(self)
99    }
100    #[inline(always)]
101    fn anchored(&self) -> bool {
102        self.is_anchored()
103    }
104    #[inline(always)]
105    fn range(&self) -> Range<usize> {
106        self.bounds()
107    }
108    #[inline(always)]
109    fn start(&self) -> usize {
110        crate::common::Input::start(self)
111    }
112    #[inline(always)]
113    fn set_start(&mut self, start: usize) {
114        crate::common::Input::set_start(self, start)
115    }
116    #[inline(always)]
117    fn set_range(&mut self, range: Range<usize>) {
118        crate::common::Input::set_bounds(self, range)
119    }
120}