pub struct BitReader<'a> {
data: &'a [u8],
pos: usize,
buf: u32,
count: u32,
}
impl<'a> BitReader<'a> {
pub fn new(data: &'a [u8]) -> Self {
let mut reader = Self {
data,
pos: 0,
buf: 0,
count: 0,
};
reader.refill();
reader
}
fn next_byte(&mut self) -> u32 {
let byte = self.data.get(self.pos).copied().unwrap_or(0);
self.pos += 1;
u32::from(byte)
}
fn refill(&mut self) {
while self.count < 16 {
self.buf = (self.buf << 8) | self.next_byte();
self.count += 8;
}
}
pub const fn peek(&self, n: u32) -> u16 {
(self.buf >> (self.count - n)) as u16
}
pub fn consume(&mut self, n: u32) {
self.count -= n;
self.buf &= (1u32 << self.count) - 1;
self.refill();
}
pub fn read(&mut self, n: u32) -> u16 {
let bits = self.peek(n);
self.consume(n);
bits
}
}
#[cfg(test)]
mod tests {
use super::BitReader;
#[test]
fn reads_bits_msb_first() {
let mut r = BitReader::new(&[0xA5, 0xC3, 0x0F, 0xF0]);
assert_eq!(r.read(4), 0xA);
assert_eq!(r.read(8), 0x5C);
assert_eq!(r.read(12), 0x30F);
}
#[test]
fn peek_does_not_consume() {
let mut r = BitReader::new(&[0xA5, 0xC3]);
assert_eq!(r.peek(4), 0xA);
assert_eq!(r.peek(4), 0xA);
r.consume(4);
assert_eq!(r.peek(4), 0x5);
}
#[test]
fn yields_zero_past_end() {
let mut r = BitReader::new(&[0xFF]);
assert_eq!(r.read(8), 0xFF);
assert_eq!(r.read(8), 0x00);
assert_eq!(r.read(16), 0x0000);
}
}