pub struct BitBuffer<'a> {
pub buffer: &'a mut [u8],
pub position: usize,
}
impl<'a> BitBuffer<'a> {
pub fn new(buffer: &'a mut [u8]) -> BitBuffer<'a> {
BitBuffer { buffer, position: 0 }
}
pub fn len(&self) -> usize {
self.buffer.len()
}
pub fn write_lte25(&mut self, bit_values: u32, num_bits: usize) {
debug_assert!(num_bits > 0 && num_bits <= 25);
debug_assert!(self.position + num_bits <= self.buffer.len() * 8);
let target = unsafe { self.buffer.as_mut_ptr().add(self.position >> 3) as *mut u32 };
let shift = 32 - (self.position & 7) - num_bits;
let curr = u32::from_be(unsafe { core::ptr::read_unaligned(target) });
let mask = ((!0u32) >> (32 - num_bits)) << shift;
let main = ((bit_values << shift) & mask) | (curr & !mask);
unsafe { core::ptr::write_unaligned(target, main.to_be()); }
self.position += num_bits;
}
pub fn write(&mut self, bit_values: u32, num_bits: usize) {
debug_assert!(num_bits > 0 && num_bits <= 32);
debug_assert!(self.position + num_bits <= self.buffer.len() * 8);
let target = unsafe { self.buffer.as_mut_ptr().add(self.position >> 3) as *mut u32 };
let shift = (32 - ((self.position as i32) & 7) - (num_bits as i32)) as i32;
let curr = u32::from_be(unsafe { core::ptr::read_unaligned(target) });
if shift < 0 {
let mask = (!0u32) >> -shift;
let main = (bit_values >> -shift) | (curr & !mask);
let tail = ((bit_values << (8 + shift)) & 0xff) as u8;
unsafe { core::ptr::write_unaligned(target, main.to_be()); }
unsafe { core::ptr::write_unaligned(target.offset(1) as *mut u8, tail); }
} else {
let mask = ((!0u32) >> (32 - num_bits)) << shift;
let main = ((bit_values << shift) & mask) | (curr & !mask);
unsafe { core::ptr::write_unaligned(target, main.to_be()); }
}
self.position += num_bits;
}
pub fn byte_align(&mut self) {
let bit = self.position & 7;
if bit == 0 { return; }
self.write_lte25(0, 8 - bit);
}
pub fn position(&self) -> usize {
self.position
}
pub fn set_position(&mut self, position: usize) {
self.position = position;
}
}