struct BitFilter { accu: u32, bits: isize, } impl BitFilter { pub fn new() -> Self { Self { bits: 0, accu: 0, } } pub fn write(&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(&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(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 each byte in s, write 7 bits skipping 1 for i in 0..10 { b.write(&src[i..], 7, 1, |c| f.push(c)); } b.write_end(|c| f.push(c)); // read 7 bits and expand to each byte of s2 skipping 1 bit let mut b = BitFilter::new(); for i in 0..10 { b.read(&mut dst[i..], 7, 1, || f.remove(0)); } // should be the same first 10 bytes as in s assert_eq!(&src[..10], &dst[..10]); }