• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use core::arch::wasm32::v128;
2 
3 use crate::memmem::{genericsimd, NeedleInfo};
4 
5 /// A `v128` accelerated vectorized substring search routine that only works on
6 /// small needles.
7 #[derive(Clone, Copy, Debug)]
8 pub(crate) struct Forward(genericsimd::Forward);
9 
10 impl Forward {
11     /// Create a new "generic simd" forward searcher. If one could not be
12     /// created from the given inputs, then None is returned.
new(ninfo: &NeedleInfo, needle: &[u8]) -> Option<Forward>13     pub(crate) fn new(ninfo: &NeedleInfo, needle: &[u8]) -> Option<Forward> {
14         if !cfg!(memchr_runtime_simd) {
15             return None;
16         }
17         genericsimd::Forward::new(ninfo, needle).map(Forward)
18     }
19 
20     /// Returns the minimum length of haystack that is needed for this searcher
21     /// to work. Passing a haystack with a length smaller than this will cause
22     /// `find` to panic.
23     #[inline(always)]
min_haystack_len(&self) -> usize24     pub(crate) fn min_haystack_len(&self) -> usize {
25         self.0.min_haystack_len::<v128>()
26     }
27 
28     #[inline(always)]
find( &self, haystack: &[u8], needle: &[u8], ) -> Option<usize>29     pub(crate) fn find(
30         &self,
31         haystack: &[u8],
32         needle: &[u8],
33     ) -> Option<usize> {
34         self.find_impl(haystack, needle)
35     }
36 
37     /// The implementation of find marked with the appropriate target feature.
38     #[target_feature(enable = "simd128")]
find_impl(&self, haystack: &[u8], needle: &[u8]) -> Option<usize>39     fn find_impl(&self, haystack: &[u8], needle: &[u8]) -> Option<usize> {
40         unsafe { genericsimd::fwd_find::<v128>(&self.0, haystack, needle) }
41     }
42 }
43 
44 #[cfg(all(test, feature = "std", not(miri)))]
45 mod tests {
46     use crate::memmem::{prefilter::PrefilterState, NeedleInfo};
47 
find( _: &mut PrefilterState, ninfo: &NeedleInfo, haystack: &[u8], needle: &[u8], ) -> Option<usize>48     fn find(
49         _: &mut PrefilterState,
50         ninfo: &NeedleInfo,
51         haystack: &[u8],
52         needle: &[u8],
53     ) -> Option<usize> {
54         super::Forward::new(ninfo, needle).unwrap().find(haystack, needle)
55     }
56 
57     #[test]
prefilter_permutations()58     fn prefilter_permutations() {
59         use crate::memmem::prefilter::tests::PrefilterTest;
60 
61         unsafe {
62             PrefilterTest::run_all_tests_filter(find, |t| {
63                 // This substring searcher only works on certain configs, so
64                 // filter our tests such that Forward::new will be guaranteed
65                 // to succeed. (And also remove tests with a haystack that is
66                 // too small.)
67                 let fwd = match super::Forward::new(&t.ninfo, &t.needle) {
68                     None => return false,
69                     Some(fwd) => fwd,
70                 };
71                 t.haystack.len() >= fwd.min_haystack_len()
72             })
73         }
74     }
75 }
76