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 find(&self, haystack: &[u8], span: Span) -> Option<Span> {
37        #[cfg(not(all(feature = "std", feature = "perf-literal-substring")))]
38        {
39            unreachable!()
40        }
41        #[cfg(all(feature = "std", feature = "perf-literal-substring"))]
42        {
43            self.finder.find(&haystack[span]).map(|i| {
44                let start = span.start + i;
45                let end = start + self.finder.needle().len();
46                Span { start, end }
47            })
48        }
49    }
50
51    fn prefix(&self, haystack: &[u8], span: Span) -> Option<Span> {
52        #[cfg(not(all(feature = "std", feature = "perf-literal-substring")))]
53        {
54            unreachable!()
55        }
56        #[cfg(all(feature = "std", feature = "perf-literal-substring"))]
57        {
58            let needle = self.finder.needle();
59            if haystack[span].starts_with(needle) {
60                Some(Span { end: span.start + needle.len(), ..span })
61            } else {
62                None
63            }
64        }
65    }
66
67    fn memory_usage(&self) -> usize {
68        #[cfg(not(all(feature = "std", feature = "perf-literal-substring")))]
69        {
70            unreachable!()
71        }
72        #[cfg(all(feature = "std", feature = "perf-literal-substring"))]
73        {
74            self.finder.needle().len()
75        }
76    }
77
78    fn is_fast(&self) -> bool {
79        #[cfg(not(all(feature = "std", feature = "perf-literal-substring")))]
80        {
81            unreachable!()
82        }
83        #[cfg(all(feature = "std", feature = "perf-literal-substring"))]
84        {
85            true
86        }
87    }
88}