pub trait Codec { type Output: Iterator; fn accept(&mut self, input: Input) -> Self::Output; fn finish(self) -> Self::Output; } #[derive(Debug)] pub struct BitDiscard { buf: u16, // Use the higher byte for storing the leftovers buf_bits: u8, // How many bits are valid in the buffer valid_len: u8, // How many bits to keep from the input shift_len: u8, // Pre-computed shift of the input byte } impl BitDiscard { pub fn new(discard: u8) -> Self { assert!(discard < 8); BitDiscard { buf: 0, buf_bits: 0, valid_len: 8 - discard, shift_len: 8 + discard, } } } impl Codec for BitDiscard { type Output = std::option::IntoIter; fn accept(&mut self, input: u8) -> Self::Output { let add = ((input as u16) << self.shift_len) >> self.buf_bits; self.buf |= add; self.buf_bits += self.valid_len; let result = if self.buf_bits >= 8 { let result = (self.buf >> 8) as u8; self.buf <<= 8; self.buf_bits -= 8; Some(result) } else { None }; result.into_iter() } fn finish(self) -> Self::Output { let result = if self.buf_bits > 0 { Some((self.buf >> 8) as u8) } else { None }; result.into_iter() } } #[derive(Debug)] pub struct BitExpand { buf: u16, // For storing the leftovers buf_bits: u8, // How many bits are valid in the buffer valid_len: u8, // How many bits are valid in the input shift_len: u8, // How many bits to shift when expanding } impl BitExpand { pub fn new(expand: u8) -> Self { assert!(expand < 8); Self { buf: 0, buf_bits: 0, valid_len: 8 - expand, shift_len: 8 + expand, } } } impl Codec for BitExpand { type Output = BitExpandIter; fn accept(&mut self, input: u8) -> Self::Output { let add = ((input as u16) << 8) >> self.buf_bits; self.buf |= add; self.buf_bits += 8; let buf = self.buf; let leftover = self.buf_bits % self.valid_len; let buf_bits = self.buf_bits - leftover; self.buf <<= buf_bits; self.buf_bits = leftover; Self::Output { buf, buf_bits, shift_len: self.shift_len, valid_len: self.valid_len, } } fn finish(self) -> Self::Output { Self::Output { buf: 0, buf_bits: 0, shift_len: 0, valid_len: self.valid_len, } } } #[derive(Debug)] pub struct BitExpandIter { buf: u16, buf_bits: u8, valid_len: u8, shift_len: u8, } impl Iterator for BitExpandIter { type Item = u8; fn next(&mut self) -> Option { if self.buf_bits < self.valid_len { None } else { let result = (self.buf >> self.shift_len) as u8; self.buf <<= self.valid_len; self.buf_bits -= self.valid_len; Some(result) } } } fn process_bytes(mut codec: C, bytes: &[u8]) -> Vec { let mut result: Vec = bytes.iter().flat_map(|byte| codec.accept(*byte)).collect(); codec.finish().for_each(|byte| result.push(byte)); result } fn print_bytes(bytes: &[u8]) { for byte in bytes { print!("{:08b} ", byte); } println!(); for byte in bytes { print!("{:02x} ", byte); } println!(); } fn main() { let original = b"STRINGIFY!"; let discard = 1; print_bytes(&original[..]); let compressed = process_bytes(BitDiscard::new(discard), &original[..]); print_bytes(&compressed); let decompressed = process_bytes(BitExpand::new(discard), &compressed); print_bytes(&decompressed); }