#[derive(Default)]
pub struct BitWriter {
pub bit_buffer: u32,
pub bits_in: u32,
}
impl BitWriter {
#[inline(always)]
pub fn write(&mut self, bits: u32, len: u32, data_buffer: &mut Vec<u8>) {
assert!(bits <= ((1u32 << len) - 1u32));
self.bit_buffer |= bits << self.bits_in;
self.bits_in += len;
self.flush_whole_bytes(data_buffer);
}
pub fn pad(&mut self, fillbit: u8, data_buffer: &mut Vec<u8>) {
let mut offset = 1;
while (self.bits_in & 7) != 0 {
self.write(if (fillbit & offset) != 0 { 1 } else { 0 }, 1, data_buffer);
offset <<= 1;
}
}
pub fn flush_whole_bytes(&mut self, data_buffer: &mut Vec<u8>) {
while self.bits_in >= 8 {
data_buffer.push(self.bit_buffer as u8);
self.bit_buffer >>= 8;
self.bits_in -= 8;
}
}
}
#[test]
fn write_simple() {
let mut b = BitWriter::default();
let mut data_buffer = Vec::new();
b.write(1, 4, &mut data_buffer);
b.write(2, 4, &mut data_buffer);
b.write(3, 4, &mut data_buffer);
b.write(4, 4, &mut data_buffer);
b.write(4, 4, &mut data_buffer);
b.write(0x56, 8, &mut data_buffer);
b.write(0x78, 8, &mut data_buffer);
b.write(0x9f, 8, &mut data_buffer);
b.write(0xfe, 8, &mut data_buffer);
b.write(0xe, 4, &mut data_buffer);
assert_eq!(data_buffer[..], [0x21, 0x43, 0x64, 0x85, 0xf7, 0xe9, 0xef]);
}
#[test]
fn write_roundtrip() {
use crate::zip_bit_reader::ZipBitReader;
let mut b = BitWriter::default();
let mut data_buffer = Vec::new();
let pattern = [
(0, 1),
(1, 1),
(1, 2),
(2, 3),
(3, 4),
(4, 5),
(4, 6),
(0x156, 9),
(0x78, 8),
(0x9f, 8),
(0xfe, 8),
(0x7fff, 15),
(0xffff, 16),
(0xe, 4),
];
for &(bits, len) in pattern.iter() {
b.write(bits, len, &mut data_buffer);
}
b.pad(0, &mut data_buffer);
b.flush_whole_bytes(&mut data_buffer);
let len = data_buffer.len() as i64;
let mut cursor = std::io::Cursor::new(data_buffer);
let mut reader = ZipBitReader::new(&mut cursor, len);
for &(bits, len) in pattern.iter() {
assert_eq!(reader.get(len).unwrap(), bits);
}
}