#![allow(dead_code)]
extern crate alloc;
use alloc::vec::Vec;
use crate::error::Error;
pub(crate) struct BitReader<'a> {
buf: &'a [u8],
bit_pos: usize,
}
impl<'a> BitReader<'a> {
pub(crate) fn new(buf: &'a [u8]) -> Self {
Self { buf, bit_pos: 0 }
}
pub(crate) fn new_at(buf: &'a [u8], bit_pos: usize) -> Self {
Self { buf, bit_pos }
}
#[inline]
pub(crate) fn total_bits(&self) -> usize {
self.buf.len() * 8
}
#[inline]
pub(crate) fn remaining(&self) -> usize {
self.total_bits().saturating_sub(self.bit_pos)
}
#[inline]
pub(crate) fn position(&self) -> usize {
self.bit_pos
}
#[inline]
pub(crate) fn bytes_consumed(&self) -> usize {
self.bit_pos / 8
}
pub(crate) fn align_to_byte(&mut self) {
let rem = self.bit_pos & 7;
if rem != 0 {
self.bit_pos += 8 - rem;
}
}
#[inline]
pub(crate) fn read_bit(&mut self) -> Result<u32, Error> {
if self.bit_pos >= self.total_bits() {
return Err(Error::UnexpectedEnd);
}
let byte = self.buf[self.bit_pos >> 3];
let shift = 7 - (self.bit_pos & 7);
let v = (byte >> shift) & 1;
self.bit_pos += 1;
Ok(v as u32)
}
pub(crate) fn read_bits(&mut self, n: u32) -> Result<u32, Error> {
debug_assert!(n <= 32);
let mut v: u32 = 0;
for _ in 0..n {
v = (v << 1) | self.read_bit()?;
}
Ok(v)
}
pub(crate) fn read_bits_48(&mut self) -> Result<u64, Error> {
let hi = self.read_bits(24)? as u64;
let lo = self.read_bits(24)? as u64;
Ok((hi << 24) | lo)
}
}
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 with_capacity(cap: usize) -> Self {
Self {
out: Vec::with_capacity(cap),
cur: 0,
nbits: 0,
}
}
#[inline]
pub(crate) fn write_bit(&mut self, b: u32) {
self.cur = (self.cur << 1) | ((b & 1) as u8);
self.nbits += 1;
if self.nbits == 8 {
self.out.push(self.cur);
self.cur = 0;
self.nbits = 0;
}
}
pub(crate) fn write_bits(&mut self, n: u32, v: u32) {
debug_assert!(n <= 32);
let mut i = n;
while i > 0 {
i -= 1;
self.write_bit((v >> i) & 1);
}
}
pub(crate) fn write_bits_48(&mut self, v: u64) {
let hi = ((v >> 24) & 0x00FF_FFFF) as u32;
let lo = (v & 0x00FF_FFFF) as u32;
self.write_bits(24, hi);
self.write_bits(24, lo);
}
pub(crate) fn align_to_byte(&mut self) {
if self.nbits > 0 {
self.cur <<= 8 - self.nbits;
self.out.push(self.cur);
self.cur = 0;
self.nbits = 0;
}
}
pub(crate) fn into_bytes(mut self) -> Vec<u8> {
if self.nbits > 0 {
self.cur <<= 8 - self.nbits;
self.out.push(self.cur);
}
self.out
}
pub(crate) fn internals_for_encoder(self) -> (Vec<u8>, u8, u8) {
(self.out, self.cur, self.nbits)
}
pub(crate) fn rehydrate(cur: u8, nbits: u8) -> Self {
debug_assert!(nbits < 8, "partial byte should hold fewer than 8 bits");
Self {
out: Vec::new(),
cur,
nbits,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
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(&bytes);
assert_eq!(r.read_bits(8).unwrap(), 0xAB);
}
#[test]
fn nibble_split() {
let mut w = BitWriter::new();
w.write_bits(4, 0xA);
w.write_bits(4, 0xB);
let bytes = w.into_bytes();
assert_eq!(bytes, vec![0xAB]);
let mut r = BitReader::new(&bytes);
assert_eq!(r.read_bits(4).unwrap(), 0xA);
assert_eq!(r.read_bits(4).unwrap(), 0xB);
}
#[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(&bytes);
assert_eq!(r.read_bits(12).unwrap(), 0xABC);
assert_eq!(r.read_bits(4).unwrap(), 0xD);
}
#[test]
fn magic_48() {
let mut w = BitWriter::new();
w.write_bits_48(0x3141_5926_5359);
let bytes = w.into_bytes();
assert_eq!(bytes, vec![0x31, 0x41, 0x59, 0x26, 0x53, 0x59]);
let mut r = BitReader::new(&bytes);
assert_eq!(r.read_bits_48().unwrap(), 0x3141_5926_5359);
}
#[test]
fn unexpected_end() {
let buf = [0u8; 0];
let mut r = BitReader::new(&buf);
assert!(r.read_bit().is_err());
}
}