Skip to content

Commit ea42b8c

Browse files
committed
Introduce Needle trait to make Avx2Searcher generic over it's needle
1 parent fd07a79 commit ea42b8c

File tree

3 files changed

+361
-227
lines changed

3 files changed

+361
-227
lines changed

src/lib.rs

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,80 @@ mod bits;
2929
mod memcmp;
3030

3131
use memchr::memchr;
32+
use std::rc::Rc;
33+
use std::sync::Arc;
34+
35+
/// Needle that can be searched for within a haystack. It allows specialized
36+
/// searcher implementations for needle sizes known at compile time.
37+
pub trait Needle {
38+
/// Set to `Some(<usize>)` if and only if the needle's length is known at compile time.
39+
const SIZE: Option<usize>;
40+
/// Return the slice corresponding to the needle.
41+
fn as_bytes(&self) -> &[u8];
42+
}
43+
44+
impl<const N: usize> Needle for [u8; N] {
45+
const SIZE: Option<usize> = Some(N);
46+
47+
#[inline]
48+
fn as_bytes(&self) -> &[u8] {
49+
self
50+
}
51+
}
52+
53+
impl Needle for [u8] {
54+
const SIZE: Option<usize> = None;
55+
56+
#[inline]
57+
fn as_bytes(&self) -> &[u8] {
58+
self
59+
}
60+
}
61+
62+
impl<N: Needle + ?Sized> Needle for Box<N> {
63+
const SIZE: Option<usize> = N::SIZE;
64+
65+
#[inline]
66+
fn as_bytes(&self) -> &[u8] {
67+
(**self).as_bytes()
68+
}
69+
}
70+
71+
impl<N: Needle + ?Sized> Needle for Rc<N> {
72+
const SIZE: Option<usize> = N::SIZE;
73+
74+
#[inline]
75+
fn as_bytes(&self) -> &[u8] {
76+
(**self).as_bytes()
77+
}
78+
}
79+
80+
impl<N: Needle + ?Sized> Needle for Arc<N> {
81+
const SIZE: Option<usize> = N::SIZE;
82+
83+
#[inline]
84+
fn as_bytes(&self) -> &[u8] {
85+
(**self).as_bytes()
86+
}
87+
}
88+
89+
impl<N: Needle + ?Sized> Needle for &N {
90+
const SIZE: Option<usize> = N::SIZE;
91+
92+
#[inline]
93+
fn as_bytes(&self) -> &[u8] {
94+
(*self).as_bytes()
95+
}
96+
}
97+
98+
impl Needle for Vec<u8> {
99+
const SIZE: Option<usize> = None;
100+
101+
#[inline]
102+
fn as_bytes(&self) -> &[u8] {
103+
self
104+
}
105+
}
32106

33107
/// Single-byte searcher using `memchr` for faster matching.
34108
pub struct MemchrSearcher(u8);
@@ -57,7 +131,7 @@ impl MemchrSearcher {
57131

58132
#[cfg(test)]
59133
mod tests {
60-
use super::MemchrSearcher;
134+
use super::{MemchrSearcher, Needle};
61135

62136
fn memchr_search(haystack: &[u8], needle: &[u8]) -> bool {
63137
MemchrSearcher::new(needle[0]).search_in(haystack)
@@ -92,4 +166,36 @@ mod tests {
92166
fn memchr_search_middle() {
93167
assert!(memchr_search(b"foobarfoo", b"b"));
94168
}
169+
170+
#[test]
171+
fn needle_array_size() {
172+
use std::rc::Rc;
173+
use std::sync::Arc;
174+
175+
assert_eq!(<[u8; 0] as Needle>::SIZE, Some(0));
176+
177+
assert_eq!(Box::<[u8; 1]>::SIZE, Some(1));
178+
179+
assert_eq!(Rc::<[u8; 2]>::SIZE, Some(2));
180+
181+
assert_eq!(Arc::<[u8; 3]>::SIZE, Some(3));
182+
183+
assert_eq!(<&[u8; 4] as Needle>::SIZE, Some(4));
184+
}
185+
186+
#[test]
187+
fn needle_slice_size() {
188+
use std::rc::Rc;
189+
use std::sync::Arc;
190+
191+
assert_eq!(Box::<[u8]>::SIZE, None);
192+
193+
assert_eq!(Vec::<u8>::SIZE, None);
194+
195+
assert_eq!(Rc::<[u8]>::SIZE, None);
196+
197+
assert_eq!(Arc::<[u8]>::SIZE, None);
198+
199+
assert_eq!(<&[u8] as Needle>::SIZE, None);
200+
}
95201
}

0 commit comments

Comments
 (0)