Skip to content

Commit 820a28f

Browse files
committed
Introduce generic Searcher trait
1 parent f2378d7 commit 820a28f

File tree

2 files changed

+72
-55
lines changed

2 files changed

+72
-55
lines changed

src/lib.rs

+59
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,65 @@ impl<T: Vector, V: Vector + From<T>> From<&VectorHash<T>> for VectorHash<V> {
192192
}
193193
}
194194

195+
trait Searcher<N: NeedleWithSize + ?Sized> {
196+
fn needle(&self) -> &N;
197+
198+
fn position(&self) -> usize;
199+
200+
#[inline]
201+
unsafe fn vector_search_in_chunk<V: Vector>(
202+
&self,
203+
haystack: &[u8],
204+
hash: &VectorHash<V>,
205+
start: *const u8,
206+
mask: i32,
207+
) -> bool {
208+
let first = Vector::loadu_si(start);
209+
let last = Vector::loadu_si(start.add(self.position()));
210+
211+
let eq_first = Vector::cmpeq_epi8(hash.first, first);
212+
let eq_last = Vector::cmpeq_epi8(hash.last, last);
213+
214+
let eq = Vector::and_si(eq_first, eq_last);
215+
let mut eq = (Vector::movemask_epi8(eq) & mask) as u32;
216+
217+
let start = start as usize - haystack.as_ptr() as usize;
218+
let chunk = haystack.as_ptr().add(start + 1);
219+
let needle = self.needle().as_bytes().as_ptr().add(1);
220+
221+
while eq != 0 {
222+
let chunk = chunk.add(eq.trailing_zeros() as usize);
223+
let equal = match N::SIZE {
224+
Some(0) => unreachable!(),
225+
Some(1) => memcmp::specialized::<0>(chunk, needle),
226+
Some(2) => memcmp::specialized::<1>(chunk, needle),
227+
Some(3) => memcmp::specialized::<2>(chunk, needle),
228+
Some(4) => memcmp::specialized::<3>(chunk, needle),
229+
Some(5) => memcmp::specialized::<4>(chunk, needle),
230+
Some(6) => memcmp::specialized::<5>(chunk, needle),
231+
Some(7) => memcmp::specialized::<6>(chunk, needle),
232+
Some(8) => memcmp::specialized::<7>(chunk, needle),
233+
Some(9) => memcmp::specialized::<8>(chunk, needle),
234+
Some(10) => memcmp::specialized::<9>(chunk, needle),
235+
Some(11) => memcmp::specialized::<10>(chunk, needle),
236+
Some(12) => memcmp::specialized::<11>(chunk, needle),
237+
Some(13) => memcmp::specialized::<12>(chunk, needle),
238+
Some(14) => memcmp::specialized::<13>(chunk, needle),
239+
Some(15) => memcmp::specialized::<14>(chunk, needle),
240+
Some(16) => memcmp::specialized::<15>(chunk, needle),
241+
_ => memcmp::generic(chunk, needle, self.needle().size() - 1),
242+
};
243+
if equal {
244+
return true;
245+
}
246+
247+
eq = bits::clear_leftmost_set(eq);
248+
}
249+
250+
false
251+
}
252+
}
253+
195254
#[cfg(test)]
196255
mod tests {
197256
use super::{MemchrSearcher, Needle};

src/x86.rs

+13-55
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![allow(clippy::missing_safety_doc)]
22

3-
use crate::{bits, memcmp, MemchrSearcher, Needle, NeedleWithSize, Vector, VectorHash};
3+
use crate::{MemchrSearcher, Needle, NeedleWithSize, Searcher, Vector, VectorHash};
44
use seq_macro::seq;
55
#[cfg(target_arch = "x86")]
66
use std::arch::x86::*;
@@ -294,60 +294,6 @@ impl<N: Needle> Avx2Searcher<N> {
294294
}
295295
}
296296

297-
#[inline]
298-
#[target_feature(enable = "avx2")]
299-
unsafe fn vector_search_in_chunk<V: Vector>(
300-
&self,
301-
haystack: &[u8],
302-
hash: &VectorHash<V>,
303-
start: *const u8,
304-
mask: i32,
305-
) -> bool {
306-
let first = Vector::loadu_si(start);
307-
let last = Vector::loadu_si(start.add(self.position));
308-
309-
let eq_first = Vector::cmpeq_epi8(hash.first, first);
310-
let eq_last = Vector::cmpeq_epi8(hash.last, last);
311-
312-
let eq = Vector::and_si(eq_first, eq_last);
313-
let mut eq = (Vector::movemask_epi8(eq) & mask) as u32;
314-
315-
let start = start as usize - haystack.as_ptr() as usize;
316-
let chunk = haystack.as_ptr().add(start + 1);
317-
let needle = self.needle.as_bytes().as_ptr().add(1);
318-
319-
while eq != 0 {
320-
let chunk = chunk.add(eq.trailing_zeros() as usize);
321-
let equal = match N::SIZE {
322-
Some(0) => unreachable!(),
323-
Some(1) => memcmp::specialized::<0>(chunk, needle),
324-
Some(2) => memcmp::specialized::<1>(chunk, needle),
325-
Some(3) => memcmp::specialized::<2>(chunk, needle),
326-
Some(4) => memcmp::specialized::<3>(chunk, needle),
327-
Some(5) => memcmp::specialized::<4>(chunk, needle),
328-
Some(6) => memcmp::specialized::<5>(chunk, needle),
329-
Some(7) => memcmp::specialized::<6>(chunk, needle),
330-
Some(8) => memcmp::specialized::<7>(chunk, needle),
331-
Some(9) => memcmp::specialized::<8>(chunk, needle),
332-
Some(10) => memcmp::specialized::<9>(chunk, needle),
333-
Some(11) => memcmp::specialized::<10>(chunk, needle),
334-
Some(12) => memcmp::specialized::<11>(chunk, needle),
335-
Some(13) => memcmp::specialized::<12>(chunk, needle),
336-
Some(14) => memcmp::specialized::<13>(chunk, needle),
337-
Some(15) => memcmp::specialized::<14>(chunk, needle),
338-
Some(16) => memcmp::specialized::<15>(chunk, needle),
339-
_ => memcmp::generic(chunk, needle, self.needle.size() - 1),
340-
};
341-
if equal {
342-
return true;
343-
}
344-
345-
eq = bits::clear_leftmost_set(eq);
346-
}
347-
348-
false
349-
}
350-
351297
#[inline]
352298
#[target_feature(enable = "avx2")]
353299
unsafe fn vector_search_in<V: Vector>(
@@ -443,6 +389,18 @@ impl<N: Needle> Avx2Searcher<N> {
443389
}
444390
}
445391

392+
impl<N: Needle> Searcher<N> for Avx2Searcher<N> {
393+
#[inline(always)]
394+
fn needle(&self) -> &N {
395+
&self.needle
396+
}
397+
398+
#[inline(always)]
399+
fn position(&self) -> usize {
400+
self.position
401+
}
402+
}
403+
446404
/// Single-substring searcher based on `Avx2Searcher` but with dynamic algorithm
447405
/// selection.
448406
///

0 commit comments

Comments
 (0)