//! `BitStreamReader` API //! //! This module provides an interface to read and write bits (and bytes) for //! huffman pub struct BitStreamReader<'src> { // buffer from which we are pulling in bits from // used in decompression. pub src: &'src [u8], // position in our buffer, pub position: usize, pub bits_left: u8, pub buffer: u64, pub over_read: usize } impl<'src> BitStreamReader<'src> { /// Create a new `BitStreamReader` instance /// /// # Expectations /// The buffer must be padded with fill bytes in the end, /// if not, this becomes UB in the refill phase. pub fn new(in_buffer: &'src [u8]) -> BitStreamReader<'src> { BitStreamReader { bits_left: 0, buffer: 0, src: in_buffer, position: 0, over_read: 0 } } /// Refill the bitstream ensuring the buffer has bits between /// 56 and 63. /// #[inline(always)] pub fn refill(&mut self) { /* * The refill always guarantees refills between 56-63 * * Bits stored will never go above 63 and if bits are in the range 56-63 no refills occur. */ let mut buf = [0; 8]; match self.src.get(self.position..self.position + 8) { Some(bytes) => { buf.copy_from_slice(bytes); // create a u64 from an array of u8's let new_buffer = u64::from_le_bytes(buf); // num indicates how many bytes we actually consumed. let num = 63 ^ self.bits_left; // offset position self.position += (num >> 3) as usize; // shift number of bits self.buffer |= new_buffer << self.bits_left; // update bits left // bits left are now between 56-63 self.bits_left |= 56; } None => self.refill_slow() } } #[inline(always)] pub fn refill_inner_loop(&mut self) { /* * The refill always guarantees refills between 56-63 * * Bits stored will never go above 63 and if bits are in the range 56-63 no refills occur. */ let mut buf = [0; 8]; if let Some(bytes) = self.src.get(self.position..self.position + 8) { { buf.copy_from_slice(bytes); // create a u64 from an array of u8's let new_buffer = u64::from_le_bytes(buf); // num indicates how many bytes we actually consumed. let num = 63 ^ self.bits_left; // offset position self.position += (num >> 3) as usize; // shift number of bits self.buffer |= new_buffer << self.bits_left; // update bits left // bits left are now between 56-63 self.bits_left |= 56; } } } #[inline(never)] fn refill_slow(&mut self) { let bytes = &self.src[self.position..]; for byte in bytes { if self.bits_left >= 56 { break; } self.buffer |= u64::from(*byte) << self.bits_left; self.bits_left += 8; self.position += 1; } while self.bits_left < 56 { self.bits_left += 8; self.over_read += 1; } } #[inline(always)] pub fn peek_bits(&self) -> usize { debug_assert!(self.bits_left >= LOOKAHEAD as u8); (self.buffer & ((1 << LOOKAHEAD) - 1)) as usize } #[inline(always)] pub fn peek_var_bits(&self, lookahead: usize) -> usize { debug_assert!(self.bits_left >= lookahead as u8); (self.buffer & ((1 << lookahead) - 1)) as usize } #[inline(always)] pub fn get_bits(&mut self, num_bits: u8) -> u64 { debug_assert!(self.bits_left >= num_bits); let mask = (1_u64 << num_bits) - 1; let value = self.buffer & mask; self.buffer >>= num_bits; self.bits_left -= num_bits; value } /// Get number of bits left in the bit buffer. pub const fn get_bits_left(&self) -> u8 { self.bits_left } /// Get position the stream is in this buffer /// Or alternatively, number of bits read. pub fn get_position(&self) -> usize { self.position .saturating_sub(usize::from(self.bits_left >> 3)) } /// Reset buffer and bits left to zero. pub fn reset(&mut self) { self.buffer = 0; self.bits_left = 0; } /// Return true if the bit buffer can satisfy /// `bits` read without refilling, pub const fn has(&self, bits: u8) -> bool { self.bits_left >= bits } #[inline(always)] pub fn drop_bits(&mut self, bits: u8) { debug_assert!(self.bits_left >= bits); self.bits_left -= bits; self.buffer >>= bits; } /// Return the remaining bytes in this stream. /// /// This does not consider bits in the bit-buffer hence /// may not be accurate pub const fn remaining_bytes(&self) -> usize { self.src.len().saturating_sub(self.position) } }