#![allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
use std::sync::OnceLock;
type MaskFn = fn(&mut [u8], [u8; 4]);
static MASK_FN: OnceLock<MaskFn> = OnceLock::new();
#[inline]
pub fn mask_inplace(buf: &mut [u8], key: [u8; 4]) {
let f = MASK_FN.get_or_init(select_impl);
f(buf, key);
}
fn select_impl() -> MaskFn {
#[cfg(target_arch = "x86_64")]
{
if std::is_x86_feature_detected!("avx2") {
return mask_avx2_wrapper;
}
}
mask_scalar
}
fn mask_scalar(buf: &mut [u8], key: [u8; 4]) {
let mut key8 = [0_u8; 8];
key8[..4].copy_from_slice(&key);
key8[4..].copy_from_slice(&key);
let key64 = u64::from_ne_bytes(key8);
let len = buf.len();
let mut i = 0;
while i + 8 <= len {
unsafe {
let p = buf.as_mut_ptr().add(i).cast::<u64>();
let v = std::ptr::read_unaligned(p);
std::ptr::write_unaligned(p, v ^ key64);
}
i += 8;
}
let mut k = 0;
while i < len {
unsafe {
*buf.get_unchecked_mut(i) ^= *key.get_unchecked(k);
}
i += 1;
k = (k + 1) & 3;
}
}
#[cfg(target_arch = "x86_64")]
fn mask_avx2_wrapper(buf: &mut [u8], key: [u8; 4]) {
unsafe { mask_avx2(buf, key) }
}
#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "avx2")]
unsafe fn mask_avx2(buf: &mut [u8], key: [u8; 4]) {
use core::arch::x86_64::{
__m256i, _mm256_loadu_si256, _mm256_set1_epi32, _mm256_storeu_si256, _mm256_xor_si256,
};
let key32 = u32::from_ne_bytes(key);
let key_vec = _mm256_set1_epi32(key32 as i32);
let buf_len = buf.len();
let mut i = 0;
while i + 32 <= buf_len {
unsafe {
let p = buf.as_mut_ptr().add(i).cast::<__m256i>();
let v = _mm256_loadu_si256(p);
let xored = _mm256_xor_si256(v, key_vec);
_mm256_storeu_si256(p, xored);
}
i += 32;
}
while i < buf_len {
buf[i] ^= key[i & 3];
i += 1;
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used, clippy::indexing_slicing)]
mod tests {
use super::*;
fn assert_inverse(data: &[u8], key: [u8; 4]) {
let mut buf = data.to_vec();
mask_inplace(&mut buf, key);
mask_inplace(&mut buf, key);
assert_eq!(&buf, data, "mask twice should yield original");
}
#[test]
fn empty_buf_is_noop() {
let mut buf: Vec<u8> = Vec::new();
mask_inplace(&mut buf, [1, 2, 3, 4]);
assert!(buf.is_empty());
}
#[test]
fn small_buf_inverse() {
assert_inverse(b"hello", [0x12, 0x34, 0x56, 0x78]);
assert_inverse(b"a", [0xFF, 0, 0, 0]);
assert_inverse(b"ab", [0x12, 0x34, 0x56, 0x78]);
assert_inverse(b"abc", [0x12, 0x34, 0x56, 0x78]);
assert_inverse(b"abcd", [0x12, 0x34, 0x56, 0x78]);
}
#[test]
fn block_boundary_inverse() {
for len in [31_usize, 32, 33, 63, 64, 65, 95, 96, 97] {
let data: Vec<u8> = (0..len).map(|i| i as u8).collect();
assert_inverse(&data, [0xDE, 0xAD, 0xBE, 0xEF]);
}
}
#[test]
fn large_buf_inverse() {
let data: Vec<u8> = (0..10_000_u32).map(|i| (i & 0xFF) as u8).collect();
assert_inverse(&data, [0x11, 0x22, 0x33, 0x44]);
}
#[test]
fn scalar_8byte_boundary_inverse() {
for len in [0_usize, 1, 7, 8, 9, 15, 16, 17, 23, 24, 25] {
let data: Vec<u8> = (0..len).map(|i| (i.wrapping_mul(73)) as u8).collect();
let key = [0xAB, 0xCD, 0xEF, 0x01];
let mut buf = data.clone();
mask_scalar(&mut buf, key);
mask_scalar(&mut buf, key);
assert_eq!(buf, data, "scalar inverse failed at len={len}");
}
}
#[test]
fn scalar_matches_known_value() {
let mut buf: [u8; 5] = *b"Hello";
mask_scalar(&mut buf, [0x37, 0xfa, 0x21, 0x3d]);
assert_eq!(buf, [0x7f, 0x9f, 0x4d, 0x51, 0x58]);
}
#[cfg(target_arch = "x86_64")]
#[test]
fn avx2_matches_scalar() {
if !std::is_x86_feature_detected!("avx2") {
return;
}
let key = [0x12_u8, 0x34, 0x56, 0x78];
for len in [0_usize, 1, 7, 31, 32, 33, 100, 1000] {
let data: Vec<u8> = (0..len).map(|i| (i * 31 % 251) as u8).collect();
let mut a = data.clone();
let mut b = data.clone();
mask_scalar(&mut a, key);
unsafe { mask_avx2(&mut b, key) };
assert_eq!(a, b, "len={len}");
}
}
}