struct BitFilter {
accu: u32,
bits: isize,
}
impl BitFilter {
pub fn new() -> Self {
Self {
bits: 0,
accu: 0,
}
}
pub fn write<F>(&mut self, mut buf: &[u8], mut nbits: usize, mut shift: usize, mut putc: F)
where F: FnMut(u8)
{
let mut accu = self.accu;
let mut bits = self.bits;
buf = &buf[shift / 8..];
shift %= 8;
while nbits != 0 || bits >= 8 {
while bits >= 8 {
bits -= 8;
putc((accu >> bits) as u8);
accu &= (1 << bits) - 1;
}
while bits < 8 && nbits != 0 {
accu = (accu << 1) | (((128 >> shift) & buf[0]) >> (7 - shift)) as u32;
nbits -= 1;
bits += 1;
shift += 1;
if shift == 8 {
shift = 0;
buf = &buf[1..];
}
}
}
self.accu = accu;
self.bits = bits;
}
pub fn read<F>(&mut self, mut buf: &mut [u8], mut nbits: usize, mut shift: usize, mut getc: F)
where F: FnMut() -> u8
{
let mut accu = self.accu;
let mut bits = self.bits;
buf = &mut buf[shift / 8..];
shift %= 8;
while nbits != 0 {
while bits != 0 && nbits != 0 {
let mask = 128 >> shift;
if accu & (1 << (bits - 1)) != 0 {
buf[0] |= mask;
} else {
buf[0] &= !mask;
}
nbits -= 1;
bits -= 1;
shift += 1;
if shift >= 8 {
shift = 0;
buf = &mut buf[1..];
}
}
if nbits == 0 { break }
accu = (accu << 8) | getc() as u32;
bits += 8;
}
self.accu = accu;
self.bits = bits;
}
pub fn write_end<F>(mut self, mut putc: F)
where F: FnMut(u8)
{
if self.bits != 0 {
self.accu <<= 8 - self.bits;
putc(self.accu as u8)
}
}
}
#[test]
fn common() {
let src = b"abcdefghijk";
let mut dst = [0u8; 11];
let mut f = Vec::new();
let mut b = BitFilter::new();
for i in 0..10 {
b.write(&src[i..], 7, 1, |c| f.push(c));
}
b.write_end(|c| f.push(c));
let mut b = BitFilter::new();
for i in 0..10 {
b.read(&mut dst[i..], 7, 1, || f.remove(0));
}
assert_eq!(&src[..10], &dst[..10]);
}