pub type Cache = u32;
#[derive(Debug, Clone)]
pub struct BitBuffer {
buffer: Cache,
bits: u32,
}
impl BitBuffer {
pub const CAPACITY: u32 = Cache::BITS;
pub const fn new(buffer: Cache, bits: u32) -> Self {
Self { buffer, bits }
}
pub const fn empty() -> Self {
Self::new(0, 0)
}
pub const fn value(&self) -> Cache {
self.buffer
}
pub const fn bits(&self) -> u32 {
self.bits
}
pub const fn push_lsb(&mut self, bits: u32, value: Cache) {
debug_assert!(self.bits + bits <= Self::CAPACITY);
debug_assert!(value & !(1 as Cache).unbounded_shl(bits).wrapping_sub(1) == 0);
self.buffer = self.buffer.unbounded_shl(bits) | value;
self.bits += bits;
}
pub const fn pop_msb(&mut self, bits: u32) -> Cache {
debug_assert!(bits <= self.bits);
let shift = self.bits - bits;
let value = self.buffer.unbounded_shr(shift);
let mask = (1 as Cache).unbounded_shl(shift).wrapping_sub(1);
self.buffer &= mask;
self.bits -= bits;
value
}
}
#[test]
fn test_fifo_lsb() {
let mut b = BitBuffer::empty();
b.push_lsb(8, 'a' as Cache);
b.push_lsb(8, 's' as Cache);
b.push_lsb(8, 'd' as Cache);
b.push_lsb(8, 'f' as Cache);
assert_eq!(b.pop_msb(8), 'a' as Cache);
assert_eq!(b.pop_msb(8), 's' as Cache);
assert_eq!(b.pop_msb(8), 'd' as Cache);
assert_eq!(b.pop_msb(8), 'f' as Cache);
}