#[cfg(target_arch = "aarch64")]
use std::arch::aarch64::*;
#[cfg(target_arch = "aarch64")]
unsafe fn find_whitespace_end_neon(bytes: &[u8], start: usize) -> usize {
let len = bytes.len();
let mut pos = start;
let v_space = vdupq_n_u8(b' ');
let v_tab = vdupq_n_u8(b'\t');
let v_cr = vdupq_n_u8(b'\r');
let v_nl = vdupq_n_u8(b'\n');
while pos + 16 <= len {
let chunk = vld1q_u8(bytes.as_ptr().add(pos));
let eq_sp = vceqq_u8(chunk, v_space);
let eq_tb = vceqq_u8(chunk, v_tab);
let eq_cr = vceqq_u8(chunk, v_cr);
let eq_nl = vceqq_u8(chunk, v_nl);
let is_ws = vorrq_u8(vorrq_u8(eq_sp, eq_tb), vorrq_u8(eq_cr, eq_nl));
if vminvq_u8(is_ws) != 0xFF {
return super::scalar::find_whitespace_end(bytes, pos);
}
pos += 16;
}
super::scalar::find_whitespace_end(bytes, pos)
}
#[cfg(target_arch = "aarch64")]
#[inline]
pub fn find_whitespace_end(bytes: &[u8], start: usize) -> usize {
unsafe { find_whitespace_end_neon(bytes, start) }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn neon_finds_end_of_spaces() {
let s: Vec<u8> = [b' '; 9].into_iter().chain([b'X']).collect();
assert_eq!(find_whitespace_end(&s, 0), 9);
}
#[test]
fn neon_handles_cross_boundary() {
let mut s = vec![b' '; 17];
s.push(b'X');
assert_eq!(find_whitespace_end(&s, 0), 17);
}
#[test]
fn neon_all_whitespace() {
let s = vec![b'\n'; 64];
assert_eq!(find_whitespace_end(&s, 0), 64);
}
#[test]
fn neon_no_whitespace() {
assert_eq!(find_whitespace_end(b"hello", 0), 0);
}
}