extern crate alloc;
use alloc::vec::Vec;
#[derive(Debug, Default)]
pub(crate) struct BitReader {
buf: Vec<u8>,
bit_pos: usize,
}
impl BitReader {
pub(crate) fn new() -> Self {
Self {
buf: Vec::new(),
bit_pos: 0,
}
}
pub(crate) fn push_bytes(&mut self, bytes: &[u8]) {
self.buf.extend_from_slice(bytes);
}
#[inline]
pub(crate) fn remaining(&self) -> usize {
(self.buf.len() * 8).saturating_sub(self.bit_pos)
}
#[inline]
pub(crate) fn snapshot(&self) -> usize {
self.bit_pos
}
#[inline]
pub(crate) fn restore(&mut self, snap: usize) {
self.bit_pos = snap;
}
pub(crate) fn read_bits(&mut self, n: u32) -> Option<u32> {
debug_assert!(n <= 16);
if self.remaining() < n as usize {
return None;
}
let mut v: u32 = 0;
for _ in 0..n {
let byte = self.buf[self.bit_pos >> 3];
let shift = 7 - (self.bit_pos & 7);
v = (v << 1) | (((byte >> shift) & 1) as u32);
self.bit_pos += 1;
}
Some(v)
}
pub(crate) fn compact(&mut self) {
let drop = self.bit_pos / 8;
if drop >= 4096 {
self.buf.drain(..drop);
self.bit_pos -= drop * 8;
}
}
pub(crate) fn clear(&mut self) {
self.buf.clear();
self.bit_pos = 0;
}
}
#[derive(Debug, Default)]
pub(crate) struct BitWriter {
out: Vec<u8>,
cur: u8,
nbits: u8,
}
impl BitWriter {
pub(crate) fn new() -> Self {
Self {
out: Vec::new(),
cur: 0,
nbits: 0,
}
}
pub(crate) fn write_bits(&mut self, n: u32, v: u32) {
debug_assert!(n <= 16);
let mut i = n;
while i > 0 {
i -= 1;
let bit = ((v >> i) & 1) as u8;
self.cur = (self.cur << 1) | bit;
self.nbits += 1;
if self.nbits == 8 {
self.out.push(self.cur);
self.cur = 0;
self.nbits = 0;
}
}
}
pub(crate) fn pad_with_ones_to_byte(&mut self) {
while self.nbits != 0 {
self.cur = (self.cur << 1) | 1;
self.nbits += 1;
if self.nbits == 8 {
self.out.push(self.cur);
self.cur = 0;
self.nbits = 0;
}
}
}
pub(crate) fn into_bytes(self) -> Vec<u8> {
self.out
}
}
#[cfg(test)]
mod tests {
use super::*;
extern crate alloc;
use alloc::vec;
#[test]
fn round_trip_msb_first() {
let mut w = BitWriter::new();
w.write_bits(8, 0xAB);
let bytes = w.into_bytes();
assert_eq!(bytes, vec![0xAB]);
let mut r = BitReader::new();
r.push_bytes(&bytes);
assert_eq!(r.read_bits(8), Some(0xAB));
}
#[test]
fn cross_byte_field() {
let mut w = BitWriter::new();
w.write_bits(12, 0xABC);
w.write_bits(4, 0xD);
let bytes = w.into_bytes();
assert_eq!(bytes, vec![0xAB, 0xCD]);
let mut r = BitReader::new();
r.push_bytes(&bytes);
assert_eq!(r.read_bits(12), Some(0xABC));
assert_eq!(r.read_bits(4), Some(0xD));
}
#[test]
fn pad_with_ones() {
let mut w = BitWriter::new();
w.write_bits(9, 0b1_1000_0000);
w.pad_with_ones_to_byte();
let bytes = w.into_bytes();
assert_eq!(bytes, vec![0xC0, 0x7F]);
}
#[test]
fn snapshot_restore() {
let mut r = BitReader::new();
r.push_bytes(&[0xAB, 0xCD]);
let snap = r.snapshot();
assert_eq!(r.read_bits(4), Some(0xA));
r.restore(snap);
assert_eq!(r.read_bits(8), Some(0xAB));
}
}