Skip to main content

regex_automata/util/prefilter/
memmem.rs

1use crate::util::{
2    prefilter::PrefilterI,
3    search::{MatchKind, Span},
4};
5
6#[derive(Clone, Debug)]
7pub(crate) struct Memmem {
8    #[cfg(not(all(feature = "std", feature = "perf-literal-substring")))]
9    _unused: (),
10    #[cfg(all(feature = "std", feature = "perf-literal-substring"))]
11    finder: memchr::memmem::Finder<'static>,
12}
13
14impl Memmem {
15    pub(crate) fn new<B: AsRef<[u8]>>(
16        _kind: MatchKind,
17        needles: &[B],
18    ) -> Option<Memmem> {
19        #[cfg(not(all(feature = "std", feature = "perf-literal-substring")))]
20        {
21            None
22        }
23        #[cfg(all(feature = "std", feature = "perf-literal-substring"))]
24        {
25            if needles.len() != 1 {
26                return None;
27            }
28            let needle = needles[0].as_ref();
29            let finder = memchr::memmem::Finder::new(needle).into_owned();
30            Some(Memmem { finder })
31        }
32    }
33}
34
35impl PrefilterI for Memmem {
36    fn name(&self) -> &'static str {
37        "memmem"
38    }
39
40    fn find(&self, haystack: &[u8], span: Span) -> Option<Span> {
41        #[cfg(not(all(feature = "std", feature = "perf-literal-substring")))]
42        {
43            unreachable!()
44        }
45        #[cfg(all(feature = "std", feature = "perf-literal-substring"))]
46        {
47            self.finder.find(&haystack[span]).map(|i| {
48                let start = span.start + i;
49                let end = start + self.finder.needle().len();
50                Span { start, end }
51            })
52        }
53    }
54
55    fn prefix(&self, haystack: &[u8], span: Span) -> Option<Span> {
56        #[cfg(not(all(feature = "std", feature = "perf-literal-substring")))]
57        {
58            unreachable!()
59        }
60        #[cfg(all(feature = "std", feature = "perf-literal-substring"))]
61        {
62            let needle = self.finder.needle();
63            if haystack[span].starts_with(needle) {
64                Some(Span { end: span.start + needle.len(), ..span })
65            } else {
66                None
67            }
68        }
69    }
70
71    fn memory_usage(&self) -> usize {
72        #[cfg(not(all(feature = "std", feature = "perf-literal-substring")))]
73        {
74            unreachable!()
75        }
76        #[cfg(all(feature = "std", feature = "perf-literal-substring"))]
77        {
78            self.finder.needle().len()
79        }
80    }
81
82    fn is_fast(&self) -> bool {
83        #[cfg(not(all(feature = "std", feature = "perf-literal-substring")))]
84        {
85            unreachable!()
86        }
87        #[cfg(all(feature = "std", feature = "perf-literal-substring"))]
88        {
89            true
90        }
91    }
92}