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