Skip to content

Commit f9346e7

Browse files
committed
Public APIs ByteSubstring & Bytes are now enums
This gains two purposes: 1. Fix ownership issue of trying to own needle `T` by both simd & fallback modules. 2. Simplifies the runtime checks done by the code when running in `maybe` mode.
1 parent 021ba3f commit f9346e7

File tree

2 files changed

+70
-68
lines changed

2 files changed

+70
-68
lines changed

src/lib.rs

Lines changed: 52 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,6 @@ extern crate proptest;
150150
#[cfg(test)]
151151
extern crate region;
152152

153-
use std::marker::PhantomData;
154-
155153
include!(concat!(env!("OUT_DIR"), "/src/macros.rs"));
156154

157155
#[cfg(any(jetscii_sse4_2 = "yes", jetscii_sse4_2 = "maybe"))]
@@ -163,49 +161,18 @@ mod fallback;
163161
#[cfg(feature = "pattern")]
164162
mod pattern;
165163

166-
macro_rules! dispatch {
167-
(simd: $simd:expr,fallback: $fallback:expr,) => {
168-
// If we can tell at compile time that we have support,
169-
// call the optimized code directly.
170-
#[cfg(jetscii_sse4_2 = "yes")]
171-
{
172-
$simd
173-
}
174-
175-
// If we can tell at compile time that we will *never* have
176-
// support, call the fallback directly.
177-
#[cfg(jetscii_sse4_2 = "no")]
178-
{
179-
$fallback
180-
}
181-
182-
// Otherwise, we will be run on a machine with or without
183-
// support, so we perform runtime detection.
184-
#[cfg(jetscii_sse4_2 = "maybe")]
185-
{
186-
if is_x86_feature_detected!("sse4.2") {
187-
$simd
188-
} else {
189-
$fallback
190-
}
191-
}
192-
};
193-
}
194-
195164
/// Searches a slice for a set of bytes. Up to 16 bytes may be used.
196-
pub struct Bytes<F>
165+
pub enum Bytes<F>
197166
where
198167
F: Fn(u8) -> bool,
199168
{
200169
#[cfg(any(jetscii_sse4_2 = "yes", jetscii_sse4_2 = "maybe"))]
201-
simd: simd::Bytes,
170+
// Since we might not use the fallback implementation, we add
171+
// PhantomData to avoid an unused type parameter
172+
SIMD(simd::Bytes, core::marker::PhantomData<F>),
202173

203174
#[cfg(any(jetscii_sse4_2 = "maybe", jetscii_sse4_2 = "no"))]
204-
fallback: fallback::Bytes<F>,
205-
206-
// Since we might not use the fallback implementation, we add this
207-
// to avoid unused type parameters.
208-
_fallback: PhantomData<F>,
175+
Fallback(fallback::Bytes<F>),
209176
}
210177

211178
impl<F> Bytes<F>
@@ -220,23 +187,34 @@ where
220187
/// the same bytes as in the array.
221188
#[allow(unused_variables)]
222189
pub /* const */ fn new(bytes: [u8; 16], len: i32, fallback: F) -> Self {
223-
Bytes {
224-
#[cfg(any(jetscii_sse4_2 = "yes", jetscii_sse4_2 = "maybe"))]
225-
simd: simd::Bytes::new(bytes, len),
190+
#[cfg(jetscii_sse4_2 = "yes")]
191+
{
192+
Self::SIMD(simd::Bytes::new(bytes, len), Default::default())
193+
}
226194

227-
#[cfg(any(jetscii_sse4_2 = "maybe", jetscii_sse4_2 = "no"))]
228-
fallback: fallback::Bytes::new(fallback),
195+
#[cfg(jetscii_sse4_2 = "no")]
196+
{
197+
Self::Fallback(fallback::Bytes::new(fallback))
198+
}
229199

230-
_fallback: PhantomData,
200+
#[cfg(jetscii_sse4_2 = "maybe")]
201+
{
202+
if is_x86_feature_detected!("sse4.2") {
203+
Self::SIMD(simd::Bytes::new(bytes, len), Default::default())
204+
} else {
205+
Self::Fallback(fallback::Bytes::new(fallback))
206+
}
231207
}
232208
}
233209

234210
/// Searches the slice for the first matching byte in the set.
235211
#[inline]
236212
pub fn find(&self, haystack: &[u8]) -> Option<usize> {
237-
dispatch! {
238-
simd: unsafe { self.simd.find(haystack) },
239-
fallback: self.fallback.find(haystack),
213+
match self {
214+
#[cfg(any(jetscii_sse4_2 = "yes", jetscii_sse4_2 = "maybe"))]
215+
Self::SIMD(needle, _) => unsafe { needle.find(haystack) },
216+
#[cfg(any(jetscii_sse4_2 = "maybe", jetscii_sse4_2 = "no"))]
217+
Self::Fallback(needle) => needle.find(haystack),
240218
}
241219
}
242220
}
@@ -282,42 +260,55 @@ where
282260
pub type AsciiCharsConst = AsciiChars<fn(u8) -> bool>;
283261

284262
/// Searches a slice for the first occurence of the subslice.
285-
pub struct ByteSubstring<T> {
263+
pub enum ByteSubstring<T> {
286264
#[cfg(any(jetscii_sse4_2 = "yes", jetscii_sse4_2 = "maybe"))]
287-
simd: simd::ByteSubstring<'a>,
265+
SIMD(simd::ByteSubstring<T>),
288266

289267
#[cfg(any(jetscii_sse4_2 = "maybe", jetscii_sse4_2 = "no"))]
290-
fallback: fallback::ByteSubstring<T>,
268+
Fallback(fallback::ByteSubstring<T>),
291269
}
292270

293271
impl<T> ByteSubstring<T>
294272
where
295273
T: AsRef<[u8]>,
296274
{
297275
pub /* const */ fn new(needle: T) -> Self {
298-
ByteSubstring {
299-
#[cfg(any(jetscii_sse4_2 = "yes", jetscii_sse4_2 = "maybe"))]
300-
simd: simd::ByteSubstring::new(needle),
276+
#[cfg(jetscii_sse4_2 = "yes")]
277+
{
278+
Self::SIMD(simd::ByteSubstring::new(needle))
279+
}
301280

302-
#[cfg(any(jetscii_sse4_2 = "maybe", jetscii_sse4_2 = "no"))]
303-
fallback: fallback::ByteSubstring::new(needle),
281+
#[cfg(jetscii_sse4_2 = "no")]
282+
{
283+
Self::Fallback(fallback::ByteSubstring::new(needle))
284+
}
285+
286+
#[cfg(jetscii_sse4_2 = "maybe")]
287+
if is_x86_feature_detected!("sse4.2") {
288+
Self::SIMD(simd::ByteSubstring::new(needle))
289+
} else {
290+
Self::Fallback(fallback::ByteSubstring::new(needle))
304291
}
305292
}
306293

307294
#[cfg(feature = "pattern")]
308295
fn needle_len(&self) -> usize {
309-
dispatch! {
310-
simd: self.simd.needle_len(),
311-
fallback: self.fallback.needle_len(),
296+
match self {
297+
#[cfg(any(jetscii_sse4_2 = "yes", jetscii_sse4_2 = "maybe"))]
298+
Self::SIMD(needle) => needle.needle_len(),
299+
#[cfg(any(jetscii_sse4_2 = "maybe", jetscii_sse4_2 = "no"))]
300+
Self::Fallback(needle) => needle.needle_len(),
312301
}
313302
}
314303

315304
/// Searches the slice for the first occurence of the subslice.
316305
#[inline]
317306
pub fn find(&self, haystack: &[u8]) -> Option<usize> {
318-
dispatch! {
319-
simd: unsafe { self.simd.find(haystack) },
320-
fallback: self.fallback.find(haystack),
307+
match self {
308+
#[cfg(any(jetscii_sse4_2 = "yes", jetscii_sse4_2 = "maybe"))]
309+
Self::SIMD(needle) => unsafe { needle.find(haystack) },
310+
#[cfg(any(jetscii_sse4_2 = "maybe", jetscii_sse4_2 = "no"))]
311+
Self::Fallback(needle) => needle.find(haystack),
321312
}
322313
}
323314
}

src/simd.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -248,12 +248,16 @@ impl<'b> PackedCompareControl for &'b Bytes {
248248
}
249249
}
250250

251-
pub struct ByteSubstring<T> {
252-
complete_needle: T,
251+
struct PackedNeedle {
253252
needle: __m128i,
254253
needle_len: i32,
255254
}
256255

256+
pub struct ByteSubstring<T> {
257+
complete_needle: T,
258+
packed_needle: PackedNeedle,
259+
}
260+
257261
impl<T> ByteSubstring<T>
258262
where
259263
T: AsRef<[u8]>,
@@ -262,12 +266,15 @@ where
262266
use std::cmp;
263267

264268
let mut simd_needle = [0; 16];
265-
let len = cmp::min(simd_needle.len(), needle.len());
269+
let len = cmp::min(simd_needle.len(), needle.as_ref().len());
266270
simd_needle[..len].copy_from_slice(&needle.as_ref()[..len]);
267-
ByteSubstring {
268-
complete_needle: needle,
271+
let packed_needle = PackedNeedle {
269272
needle: unsafe { TransmuteToSimd { bytes: simd_needle }.simd },
270273
needle_len: len as i32,
274+
};
275+
ByteSubstring {
276+
complete_needle: needle,
277+
packed_needle,
271278
}
272279
}
273280

@@ -281,7 +288,10 @@ where
281288
pub unsafe fn find(&self, haystack: &[u8]) -> Option<usize> {
282289
let mut offset = 0;
283290

284-
while let Some(idx) = find(PackedCompare::<_, _SIDD_CMP_EQUAL_ORDERED>(self), &haystack[offset..]) {
291+
while let Some(idx) = find(
292+
PackedCompare::<_, _SIDD_CMP_EQUAL_ORDERED>(&self.packed_needle),
293+
&haystack[offset..],
294+
) {
285295
let abs_offset = offset + idx;
286296
// Found a match, but is it really?
287297
if haystack[abs_offset..].starts_with(self.complete_needle.as_ref()) {
@@ -296,10 +306,11 @@ where
296306
}
297307
}
298308

299-
impl<'a, 'b> PackedCompareControl for &'b ByteSubstring<'a> {
309+
impl<'b> PackedCompareControl for &'b PackedNeedle {
300310
fn needle(&self) -> __m128i {
301311
self.needle
302312
}
313+
303314
fn needle_len(&self) -> i32 {
304315
self.needle_len
305316
}

0 commit comments

Comments
 (0)