#[inline]
#[must_use]
pub(crate) fn first_byte_in_slice(haystack: &[u8], needle: u8) -> Option<usize> {
#[cfg(feature = "memchr")]
{
memchr::memchr(needle, haystack)
}
#[cfg(not(feature = "memchr"))]
{
swar_first_byte(haystack, needle)
}
}
#[inline]
#[must_use]
pub(crate) unsafe fn first_byte_in_raw(start: usize, len: usize, needle: u8) -> Option<usize> {
let haystack: &[u8] = core::slice::from_raw_parts(start as *const u8, len);
swar_first_byte(haystack, needle)
}
#[inline]
fn swar_first_byte(haystack: &[u8], needle: u8) -> Option<usize> {
const LO: usize = usize::from_le_bytes([0x01; core::mem::size_of::<usize>()]);
const HI: usize = usize::from_le_bytes([0x80; core::mem::size_of::<usize>()]);
let needle_word = (needle as usize) * LO;
let chunks = haystack.chunks_exact(core::mem::size_of::<usize>());
let remainder = chunks.remainder();
let mut idx = 0usize;
for chunk in chunks.clone() {
let word = usize::from_le_bytes(chunk.try_into().unwrap());
let xor = word ^ needle_word;
if (xor.wrapping_sub(LO)) & !xor & HI != 0 {
for (j, &b) in chunk.iter().enumerate() {
if b == needle {
return Some(idx + j);
}
}
}
idx += core::mem::size_of::<usize>();
}
for (j, &b) in remainder.iter().enumerate() {
if b == needle {
return Some(idx + j);
}
}
None
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn finds_first_in_aligned_chunk() {
let buf = b"hello world";
assert_eq!(first_byte_in_slice(buf, b'o'), Some(4));
}
#[test]
fn finds_in_tail() {
let mut buf = vec![0u8; 17];
buf[16] = 0x42;
assert_eq!(first_byte_in_slice(&buf, 0x42), Some(16));
}
#[test]
fn returns_none_when_absent() {
let buf = vec![0u8; 1024];
assert_eq!(first_byte_in_slice(&buf, 0xFF), None);
}
#[test]
fn empty_slice_returns_none() {
assert_eq!(first_byte_in_slice(&[], 0x42), None);
}
#[test]
fn swar_handles_high_bit_bytes_without_false_positive() {
let buf = vec![0xFFu8; 64];
assert_eq!(swar_first_byte(&buf, 0x42), None);
}
#[test]
fn swar_finds_needle_among_high_bit_bytes() {
let mut buf = vec![0xFFu8; 64];
buf[37] = 0x42;
assert_eq!(swar_first_byte(&buf, 0x42), Some(37));
}
#[test]
fn first_byte_in_raw_finds_needle() {
let buf = b"sigscan-test";
let result = unsafe { first_byte_in_raw(buf.as_ptr() as usize, buf.len(), b's') };
assert_eq!(result, Some(0));
let result_t = unsafe { first_byte_in_raw(buf.as_ptr() as usize, buf.len(), b't') };
assert_eq!(result_t, Some(8));
}
#[test]
fn first_byte_in_raw_returns_none_when_absent() {
let buf = vec![0u8; 64];
let result = unsafe { first_byte_in_raw(buf.as_ptr() as usize, buf.len(), 0xFF) };
assert_eq!(result, None);
}
}