Signed-off-by: Alexey Galakhov <agalakhov@snapview.de>pull/12/head
parent
b9f71029a3
commit
01a9211a84
@ -0,0 +1,71 @@ |
||||
use std::mem::transmute; |
||||
use rand; |
||||
|
||||
/// Generate a random frame mask.
|
||||
#[inline] |
||||
pub fn generate_mask() -> [u8; 4] { |
||||
rand::random() |
||||
} |
||||
|
||||
/// Mask/unmask a frame.
|
||||
#[inline] |
||||
pub fn apply_mask(buf: &mut [u8], mask: &[u8; 4]) { |
||||
// Assume that the memory is 32-bytes aligned.
|
||||
// FIXME: this assumption is not correct.
|
||||
unsafe { apply_mask_aligned32(buf, mask) } |
||||
} |
||||
|
||||
/// A safe unoptimized mask application.
|
||||
#[inline] |
||||
fn apply_mask_fallback(buf: &mut [u8], mask: &[u8; 4]) { |
||||
for (i, byte) in buf.iter_mut().enumerate() { |
||||
*byte ^= mask[i & 3]; |
||||
} |
||||
} |
||||
|
||||
/// Faster version of `apply_mask()` which operates on 4-byte blocks.
|
||||
///
|
||||
/// Safety: `buf` must be at least 4-bytes aligned.
|
||||
#[inline] |
||||
unsafe fn apply_mask_aligned32(buf: &mut [u8], mask: &[u8; 4]) { |
||||
debug_assert_eq!(buf.as_ptr() as usize % 4, 0); |
||||
|
||||
let mask_u32 = transmute(*mask); |
||||
|
||||
let mut ptr = buf.as_mut_ptr() as *mut u32; |
||||
for _ in 0..(buf.len() / 4) { |
||||
*ptr ^= mask_u32; |
||||
ptr = ptr.offset(1); |
||||
} |
||||
|
||||
// Possible last block with less than 4 bytes.
|
||||
let last_block_start = buf.len() & !3; |
||||
let last_block = &mut buf[last_block_start..]; |
||||
apply_mask_fallback(last_block, mask); |
||||
} |
||||
|
||||
#[cfg(test)] |
||||
mod tests { |
||||
|
||||
use super::{apply_mask_fallback, apply_mask_aligned32}; |
||||
|
||||
#[test] |
||||
fn test_apply_mask() { |
||||
let mask = [ |
||||
0x6d, 0xb6, 0xb2, 0x80, |
||||
]; |
||||
let unmasked = vec![ |
||||
0xf3, 0x00, 0x01, 0x02, 0x03, 0x80, 0x81, 0x82, 0xff, 0xfe, 0x00, |
||||
]; |
||||
|
||||
let mut masked = unmasked.clone(); |
||||
apply_mask_fallback(&mut masked, &mask); |
||||
|
||||
let mut masked_aligned = unmasked.clone(); |
||||
unsafe { apply_mask_aligned32(&mut masked_aligned, &mask) }; |
||||
|
||||
assert_eq!(masked, masked_aligned); |
||||
} |
||||
|
||||
} |
||||
|
Loading…
Reference in new issue