Skip to main content

cheetah_string/
search.rs

1pub(crate) fn find_bytes(haystack: &[u8], needle: &[u8]) -> Option<usize> {
2    if needle.is_empty() {
3        return Some(0);
4    }
5
6    if needle.len() == 1 {
7        return memchr::memchr(needle[0], haystack);
8    }
9
10    memchr::memmem::find(haystack, needle)
11}
12
13pub(crate) fn rfind_bytes(haystack: &[u8], needle: &[u8]) -> Option<usize> {
14    if needle.is_empty() {
15        return Some(haystack.len());
16    }
17
18    if needle.len() == 1 {
19        return memchr::memrchr(needle[0], haystack);
20    }
21
22    memchr::memmem::rfind(haystack, needle)
23}
24
25/// Reusable substring finder for repeated searches with the same needle.
26pub struct CheetahFinder<'a> {
27    needle: &'a str,
28    finder: Option<memchr::memmem::Finder<'a>>,
29}
30
31impl<'a> CheetahFinder<'a> {
32    /// Creates a reusable finder for `needle`.
33    #[inline]
34    pub fn new(needle: &'a str) -> Self {
35        let finder = (needle.len() > 1).then(|| memchr::memmem::Finder::new(needle.as_bytes()));
36        Self { needle, finder }
37    }
38
39    /// Returns the needle used by this finder.
40    #[inline]
41    pub fn needle(&self) -> &'a str {
42        self.needle
43    }
44
45    /// Finds the first occurrence of the needle in `haystack`.
46    #[inline]
47    pub fn find_in<S>(&self, haystack: &S) -> Option<usize>
48    where
49        S: AsRef<str> + ?Sized,
50    {
51        let haystack = haystack.as_ref().as_bytes();
52
53        if self.needle.is_empty() {
54            return Some(0);
55        }
56
57        if self.needle.len() == 1 {
58            return memchr::memchr(self.needle.as_bytes()[0], haystack);
59        }
60
61        self.finder
62            .as_ref()
63            .and_then(|finder| finder.find(haystack))
64    }
65
66    /// Returns whether the needle occurs in `haystack`.
67    #[inline]
68    pub fn is_match<S>(&self, haystack: &S) -> bool
69    where
70        S: AsRef<str> + ?Sized,
71    {
72        self.find_in(haystack).is_some()
73    }
74}