use std::io::{Read, Seek, SeekFrom};
pub const XOR_MASK_LEN: usize = 8;
pub struct XorReader<R: Read> {
inner: R,
pos: u64,
mask: Option<[u8; XOR_MASK_LEN]>,
}
impl<R: Read> XorReader<R> {
pub fn new(reader: R, xor_mask: Option<[u8; 8]>) -> Self {
Self {
inner: reader,
pos: 0,
mask: xor_mask,
}
}
}
impl<R: Read> Read for XorReader<R> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let size = self.inner.read(buf)?;
if let Some(mask) = self.mask {
for x in &mut buf[..size] {
*x ^= mask[(self.pos % mask.len() as u64) as usize];
self.pos += 1;
}
}
Ok(size)
}
}
impl<R: Seek + Read> Seek for XorReader<R> {
fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
let result = self.inner.seek(pos);
self.pos = self.inner.stream_position()?;
result
}
}