use super::request::is_valid_uri_byte;
#[inline]
pub fn match_path_vectored(buf: &[u8]) -> usize {
swar_match_path_vectored(buf)
}
#[inline]
pub fn match_uri_vectored(buf: &[u8]) -> usize {
swar_match_uri_vectored(buf)
}
#[inline]
fn swar_match_path_vectored(buf: &[u8]) -> usize {
let len = buf.len();
let mut i = 0;
while i + BLOCK_SIZE <= len {
let x = unsafe { core::ptr::read_unaligned(buf.as_ptr().add(i) as *const usize) };
const ONE: usize = uniform_block(0x01);
const M128: usize = uniform_block(0x80);
const QQ: usize = uniform_block(b'?');
const SP: usize = uniform_block(b' ');
let yq = x ^ QQ;
let hq = yq.wrapping_sub(ONE) & !yq & M128;
let ys = x ^ SP;
let hs = ys.wrapping_sub(ONE) & !ys & M128;
let hit = hq | hs;
if hit != 0 {
return i + offsetnz(hit);
}
i += BLOCK_SIZE;
}
while i < len {
let b = unsafe { *buf.get_unchecked(i) };
if b == b'?' || b == b' ' {
break;
}
i += 1;
}
i
}
#[inline]
fn swar_match_uri_vectored(buf: &[u8]) -> usize {
let len = buf.len();
let mut i = 0;
while i + BLOCK_SIZE <= len {
let x = unsafe { core::ptr::read_unaligned(buf.as_ptr().add(i) as *const usize) };
const M: u8 = 0x21;
const BM: usize = uniform_block(M);
const ONE: usize = uniform_block(0x01);
const DEL: usize = uniform_block(0x7f);
const M128: usize = uniform_block(128);
let lt = x.wrapping_sub(BM) & !x;
let y = x ^ DEL;
let eq = y.wrapping_sub(ONE) & !y;
let hit = (lt | eq) & M128;
if hit != 0 {
return i + offsetnz(hit);
}
i += BLOCK_SIZE;
}
while i < len {
if !is_valid_uri_byte(unsafe { *buf.get_unchecked(i) }) {
break;
}
i += 1;
}
i
}
const BLOCK_SIZE: usize = core::mem::size_of::<usize>();
const fn uniform_block(b: u8) -> usize {
usize::from_ne_bytes([b; BLOCK_SIZE])
}
#[inline]
fn offsetnz(block: usize) -> usize {
if block == 0 {
return BLOCK_SIZE;
}
for (i, b) in block.to_ne_bytes().iter().copied().enumerate() {
if b != 0 {
return i;
}
}
unreachable!()
}