use crate::BufMut;
pub struct Masker<'w> {
key: [u8; 4],
pos: usize,
end: &'w mut dyn BufMut,
}
impl<'w> Masker<'w> {
pub fn new(key: [u8; 4], endpoint: &'w mut dyn BufMut) -> Self {
Masker {
key,
pos: 0,
end: endpoint,
}
}
}
unsafe impl<'w> BufMut for Masker<'w> {
fn remaining_mut(&self) -> usize {
self.end.remaining_mut()
}
unsafe fn advance_mut(&mut self, cnt: usize) {
self.end.advance_mut(cnt)
}
fn chunk_mut(&mut self) -> &mut [std::mem::MaybeUninit<u8>] {
self.end.chunk_mut()
}
fn put_slice(&mut self, src: &[u8]) -> usize {
let mut buf = Vec::with_capacity(src.len());
for &byte in src.iter() {
buf.push(byte ^ self.key[self.pos]);
self.pos = (self.pos + 1) % self.key.len();
}
self.inner_put_slice(&buf)
}
}
pub fn mask_data(mask: [u8; 4], data: &[u8]) -> Vec<u8> {
let mut out = Vec::with_capacity(data.len());
let zip_iter = data.iter().zip(mask.iter().cycle());
for (&buf_item, &key_item) in zip_iter {
out.push(buf_item ^ key_item);
}
out
}
#[cfg(test)]
mod tests {
use test;
use super::*;
#[test]
fn test_mask_data() {
let key = [1u8, 2u8, 3u8, 4u8];
let original = vec![10u8, 11u8, 12u8, 13u8, 14u8, 15u8, 16u8, 17u8];
let expected = vec![11u8, 9u8, 15u8, 9u8, 15u8, 13u8, 19u8, 21u8];
let obtained = mask_data(key, &original[..]);
let reversed = mask_data(key, &obtained[..]);
assert_eq!(original, reversed);
assert_eq!(obtained, expected);
}
}