pub fn xor_in_place(dst: &mut [u8], key: &[u8]) {
if key.is_empty() {
return;
}
for (i, b) in dst.iter_mut().enumerate() {
*b ^= key[i % key.len()];
}
}
pub fn set_bit_le(buf: &mut [u8], idx: usize) {
buf[idx >> 3] |= 1 << (idx & 7);
}
pub fn get_bit_le(buf: &[u8], idx: usize) -> bool {
(buf[idx >> 3] & (1 << (idx & 7))) != 0
}
pub fn has_type(t: u8, mask: u8) -> bool {
t & mask == mask
}
pub fn common_prefix<'a>(a: &'a [u8], b: &[u8]) -> &'a [u8] {
let n = a.len().min(b.len());
for i in 0..n {
if a[i] != b[i] {
return &a[..i];
}
}
&a[..n]
}
pub fn pad_end_to_multiple(mut buf: Vec<u8>, m: usize, pad: u8) -> Vec<u8> {
let r = buf.len() % m;
if r == 0 {
return buf;
}
let needed = m - r;
buf.resize(buf.len() + needed, pad);
buf
}
pub struct Reader<'a> {
buf: &'a [u8],
pos: usize,
}
impl<'a> Reader<'a> {
pub fn new(buf: &'a [u8]) -> Self {
Self { buf, pos: 0 }
}
pub fn read(&mut self, n: usize) -> Option<&'a [u8]> {
if self.pos + n > self.buf.len() {
return None;
}
let out = &self.buf[self.pos..self.pos + n];
self.pos += n;
Some(out)
}
pub fn read_byte(&mut self) -> Option<u8> {
Some(self.read(1)?[0])
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn xor_round_trip() {
let mut buf = vec![0xaa; 10];
let key = b"key";
let original = buf.clone();
xor_in_place(&mut buf, key);
xor_in_place(&mut buf, key);
assert_eq!(buf, original);
}
#[test]
fn xor_empty_key_noop() {
let mut buf = vec![1, 2, 3];
let original = buf.clone();
xor_in_place(&mut buf, &[]);
assert_eq!(buf, original);
}
#[test]
fn set_get_bit_le() {
let mut buf = [0u8; 4];
set_bit_le(&mut buf, 0);
set_bit_le(&mut buf, 9);
set_bit_le(&mut buf, 17);
assert!(get_bit_le(&buf, 0));
assert!(get_bit_le(&buf, 9));
assert!(get_bit_le(&buf, 17));
assert!(!get_bit_le(&buf, 1));
assert_eq!(buf, [0b0000_0001, 0b0000_0010, 0b0000_0010, 0]);
}
#[test]
fn common_prefix_returns_shared() {
assert_eq!(common_prefix(b"hello", b"help"), b"hel");
assert_eq!(common_prefix(b"abc", b"abc"), b"abc");
assert_eq!(common_prefix(b"abc", b"xyz"), b"" as &[u8]);
assert_eq!(common_prefix(b"abc", b"ab"), b"ab");
}
#[test]
fn pad_end_aligns_to_multiple() {
let padded = pad_end_to_multiple(vec![1, 2, 3], 8, 0xaa);
assert_eq!(padded, vec![1, 2, 3, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa]);
let already_aligned = pad_end_to_multiple(vec![1; 8], 8, 0);
assert_eq!(already_aligned, vec![1; 8]);
}
}