#[cfg(not(all(target_arch = "aarch64", feature = "simd")))]
#[inline]
fn unmask_easy(payload: &mut [u8], mask: [u8; 4]) {
for i in 0..payload.len() {
payload[i] ^= mask[i & 3];
}
}
#[inline]
pub fn unmask(payload: &mut [u8], mask: [u8; 4]) {
#[cfg(not(all(target_arch = "aarch64", feature = "simd")))]
return unmask_easy(payload, mask);
#[cfg(all(target_arch = "aarch64", feature = "simd"))]
unsafe {
extern "C" {
fn unmask(payload: *mut u8, mask: *const u8, len: usize);
}
unmask(payload.as_mut_ptr(), mask.as_ptr(), payload.len());
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_unmask() {
let mut payload = [0u8; 33];
let mask = [1, 2, 3, 4];
unmask(&mut payload, mask);
assert_eq!(
&payload,
&[
1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4,
1, 2, 3, 4, 1, 2, 3, 4, 1
]
);
}
#[test]
fn length_variation_unmask() {
for len in &[0, 2, 3, 8, 16, 18, 31, 32, 40] {
let mut payload = vec![0u8; *len];
let mask = [1, 2, 3, 4];
unmask(&mut payload, mask);
let expected = (0..*len).map(|i| (i & 3) as u8 + 1).collect::<Vec<_>>();
assert_eq!(payload, expected);
}
}
#[test]
fn length_variation_unmask_2() {
for len in &[0, 2, 3, 8, 16, 18, 31, 32, 40] {
let mut payload = vec![0u8; *len];
let mask = rand::random::<[u8; 4]>();
unmask(&mut payload, mask);
let expected = (0..*len).map(|i| mask[i & 3]).collect::<Vec<_>>();
assert_eq!(payload, expected);
}
}
}