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