use num_primitive::{PrimitiveInteger, PrimitiveNumber};
use crate::codes::params::{DefaultReadParams, ReadParams};
use crate::traits::*;
#[cfg(feature = "mem_dbg")]
use mem_dbg::{MemDbg, MemSize};
type BB<WR> = <<WR as WordRead>::Word as DoubleType>::DoubleType;
#[derive(Debug)]
#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
pub struct BufBitReader<E: Endianness, WR: WordRead, RP: ReadParams = DefaultReadParams>
where
WR::Word: DoubleType,
{
backend: WR,
buffer: BB<WR>,
bits_in_buffer: usize,
_marker: core::marker::PhantomData<(E, RP)>,
}
#[cfg(feature = "std")]
pub fn from_path<E: Endianness, W: Word + DoubleType>(
path: impl AsRef<std::path::Path>,
) -> std::io::Result<
BufBitReader<E, super::WordAdapter<W, std::io::BufReader<std::fs::File>>, DefaultReadParams>,
>
where
W::Bytes: Default + AsMut<[u8]>,
{
Ok(from_file::<E, W>(std::fs::File::open(path)?))
}
#[must_use]
#[cfg(feature = "std")]
pub fn from_file<E: Endianness, W: Word + DoubleType>(
file: std::fs::File,
) -> BufBitReader<E, super::WordAdapter<W, std::io::BufReader<std::fs::File>>, DefaultReadParams>
where
W::Bytes: Default + AsMut<[u8]>,
{
BufBitReader::new(super::WordAdapter::new(std::io::BufReader::new(file)))
}
impl<E: Endianness, WR: WordRead + Clone, RP: ReadParams> core::clone::Clone
for BufBitReader<E, WR, RP>
where
WR::Word: DoubleType,
{
fn clone(&self) -> Self {
Self {
backend: self.backend.clone(),
buffer: self.buffer,
bits_in_buffer: self.bits_in_buffer,
_marker: core::marker::PhantomData,
}
}
}
impl<E: Endianness, WR: WordRead, RP: ReadParams> BufBitReader<E, WR, RP>
where
WR::Word: DoubleType,
{
const WORD_BITS: usize = WR::Word::BITS as usize;
const BUFFER_BITS: usize = BB::<WR>::BITS as usize;
#[must_use]
pub const fn new(backend: WR) -> Self {
Self {
backend,
buffer: BB::<WR>::ZERO,
bits_in_buffer: 0,
_marker: core::marker::PhantomData,
}
}
#[must_use]
pub fn into_inner(self) -> WR {
self.backend
}
}
impl<WR: WordRead, RP: ReadParams> BufBitReader<BE, WR, RP>
where
WR::Word: DoubleType,
{
#[inline(always)]
fn refill(&mut self) -> Result<(), <WR as WordRead>::Error> {
debug_assert!(Self::BUFFER_BITS - self.bits_in_buffer >= Self::WORD_BITS);
let new_word: BB<WR> = self.backend.read_word()?.to_be().as_double();
self.bits_in_buffer += Self::WORD_BITS;
self.buffer |= new_word << (Self::BUFFER_BITS - self.bits_in_buffer);
Ok(())
}
}
impl<WR: WordRead, RP: ReadParams> BitRead<BE> for BufBitReader<BE, WR, RP>
where
WR::Word: DoubleType,
{
type Error = <WR as WordRead>::Error;
type PeekWord = BB<WR>;
const PEEK_BITS: usize = <WR as WordRead>::Word::BITS as usize + 1;
#[inline(always)]
fn peek_bits(&mut self, n_bits: usize) -> Result<Self::PeekWord, Self::Error> {
debug_assert!(n_bits > 0);
debug_assert!(n_bits <= Self::PeekWord::BITS as usize);
if n_bits > self.bits_in_buffer {
self.refill()?;
}
debug_assert!(n_bits <= self.bits_in_buffer);
Ok(self.buffer >> (Self::BUFFER_BITS - n_bits))
}
#[inline(always)]
fn skip_bits_after_peek(&mut self, n_bits: usize) {
self.bits_in_buffer -= n_bits;
self.buffer <<= n_bits;
}
#[inline]
fn read_bits(&mut self, mut num_bits: usize) -> Result<u64, Self::Error> {
debug_assert!(num_bits <= 64);
debug_assert!(self.bits_in_buffer < Self::BUFFER_BITS);
if num_bits <= self.bits_in_buffer {
let result: u64 = (self.buffer >> (Self::BUFFER_BITS - num_bits - 1) >> 1_u32).as_to();
self.bits_in_buffer -= num_bits;
self.buffer <<= num_bits;
return Ok(result);
}
let mut result: u64 =
(self.buffer >> (Self::BUFFER_BITS - 1 - self.bits_in_buffer) >> 1_u8).as_to();
num_bits -= self.bits_in_buffer;
while num_bits > Self::WORD_BITS {
let new_word: u64 = self.backend.read_word()?.to_be().as_u64();
result = (result << Self::WORD_BITS) | new_word;
num_bits -= Self::WORD_BITS;
}
debug_assert!(num_bits > 0);
debug_assert!(num_bits <= Self::WORD_BITS);
let new_word = self.backend.read_word()?.to_be();
self.bits_in_buffer = Self::WORD_BITS - num_bits;
let upcast: u64 = new_word.as_u64();
let final_bits: u64 = upcast >> self.bits_in_buffer;
result = (result << (num_bits - 1) << 1) | final_bits;
self.buffer = (new_word.as_double() << (Self::BUFFER_BITS - self.bits_in_buffer - 1)) << 1;
Ok(result)
}
#[inline]
fn read_unary(&mut self) -> Result<u64, Self::Error> {
debug_assert!(self.bits_in_buffer < Self::BUFFER_BITS);
let zeros: usize = self.buffer.leading_zeros() as _;
if zeros < self.bits_in_buffer {
self.buffer = self.buffer << zeros << 1;
self.bits_in_buffer -= zeros + 1;
return Ok(zeros as u64);
}
let mut result: u64 = self.bits_in_buffer as _;
loop {
let new_word = self.backend.read_word()?.to_be();
if new_word != WR::Word::ZERO {
let zeros: usize = new_word.leading_zeros() as _;
self.buffer = new_word.as_double() << (Self::WORD_BITS + zeros) << 1;
self.bits_in_buffer = Self::WORD_BITS - zeros - 1;
return Ok(result + zeros as u64);
}
result += Self::WORD_BITS as u64;
}
}
#[inline]
fn skip_bits(&mut self, mut n_bits: usize) -> Result<(), Self::Error> {
debug_assert!(self.bits_in_buffer < Self::BUFFER_BITS);
if n_bits <= self.bits_in_buffer {
self.bits_in_buffer -= n_bits;
self.buffer <<= n_bits;
return Ok(());
}
n_bits -= self.bits_in_buffer;
while n_bits > Self::WORD_BITS {
let _ = self.backend.read_word()?;
n_bits -= Self::WORD_BITS;
}
let new_word = self.backend.read_word()?.to_be();
self.bits_in_buffer = Self::WORD_BITS - n_bits;
self.buffer = new_word.as_double() << (Self::BUFFER_BITS - 1 - self.bits_in_buffer) << 1;
Ok(())
}
#[cfg(not(feature = "no_copy_impls"))]
fn copy_to<F: Endianness, W: BitWrite<F>>(
&mut self,
bit_write: &mut W,
mut n: u64,
) -> Result<(), CopyError<Self::Error, W::Error>> {
let from_buffer = Ord::min(n, self.bits_in_buffer as _);
self.buffer = self.buffer.rotate_left(from_buffer as _);
#[allow(unused_mut)]
let mut self_buffer_u64: u64 = self.buffer.as_to();
#[cfg(feature = "checks")]
{
if n < 64 {
self_buffer_u64 &= (1_u64 << n) - 1;
}
}
bit_write
.write_bits(self_buffer_u64, from_buffer as usize)
.map_err(CopyError::WriteError)?;
n -= from_buffer;
if n == 0 {
self.bits_in_buffer -= from_buffer as usize;
return Ok(());
}
while n > Self::WORD_BITS as u64 {
bit_write
.write_bits(
self.backend
.read_word()
.map_err(CopyError::ReadError)?
.to_be()
.as_u64(),
Self::WORD_BITS,
)
.map_err(CopyError::WriteError)?;
n -= Self::WORD_BITS as u64;
}
debug_assert!(n > 0);
let new_word = self
.backend
.read_word()
.map_err(CopyError::ReadError)?
.to_be();
self.bits_in_buffer = Self::WORD_BITS - n as usize;
bit_write
.write_bits((new_word >> self.bits_in_buffer).as_u64(), n as usize)
.map_err(CopyError::WriteError)?;
self.buffer = new_word
.as_double()
.rotate_right(Self::WORD_BITS as u32 - n as u32);
Ok(())
}
}
impl<WR: WordRead + WordSeek<Error = <WR as WordRead>::Error>, RP: ReadParams> BitSeek
for BufBitReader<BE, WR, RP>
where
WR::Word: DoubleType,
{
type Error = <WR as WordSeek>::Error;
#[inline]
fn bit_pos(&mut self) -> Result<u64, Self::Error> {
Ok(self.backend.word_pos()? * Self::WORD_BITS as u64 - self.bits_in_buffer as u64)
}
#[inline]
fn set_bit_pos(&mut self, bit_index: u64) -> Result<(), Self::Error> {
self.backend
.set_word_pos(bit_index / Self::WORD_BITS as u64)?;
let bit_offset = (bit_index % Self::WORD_BITS as u64) as usize;
self.buffer = BB::<WR>::ZERO;
self.bits_in_buffer = 0;
if bit_offset != 0 {
let new_word: BB<WR> = self.backend.read_word()?.to_be().as_double();
self.bits_in_buffer = Self::WORD_BITS - bit_offset;
self.buffer = new_word << (Self::BUFFER_BITS - self.bits_in_buffer);
}
Ok(())
}
}
impl<WR: WordRead, RP: ReadParams> BufBitReader<LE, WR, RP>
where
WR::Word: DoubleType,
{
#[inline(always)]
fn refill(&mut self) -> Result<(), <WR as WordRead>::Error> {
debug_assert!(Self::BUFFER_BITS - self.bits_in_buffer >= Self::WORD_BITS);
let new_word: BB<WR> = self.backend.read_word()?.to_le().as_double();
self.buffer |= new_word << self.bits_in_buffer;
self.bits_in_buffer += Self::WORD_BITS;
Ok(())
}
}
impl<WR: WordRead, RP: ReadParams> BitRead<LE> for BufBitReader<LE, WR, RP>
where
WR::Word: DoubleType,
{
type Error = <WR as WordRead>::Error;
type PeekWord = BB<WR>;
const PEEK_BITS: usize = <WR as WordRead>::Word::BITS as usize + 1;
#[inline(always)]
fn peek_bits(&mut self, n_bits: usize) -> Result<Self::PeekWord, Self::Error> {
debug_assert!(n_bits > 0);
debug_assert!(n_bits <= Self::PeekWord::BITS as usize);
if n_bits > self.bits_in_buffer {
self.refill()?;
}
debug_assert!(n_bits <= self.bits_in_buffer);
let shamt = Self::BUFFER_BITS - n_bits;
Ok((self.buffer << shamt) >> shamt)
}
#[inline(always)]
fn skip_bits_after_peek(&mut self, n_bits: usize) {
self.bits_in_buffer -= n_bits;
self.buffer >>= n_bits;
}
#[inline]
fn read_bits(&mut self, mut num_bits: usize) -> Result<u64, Self::Error> {
debug_assert!(num_bits <= 64);
debug_assert!(self.bits_in_buffer < Self::BUFFER_BITS);
if num_bits <= self.bits_in_buffer {
let result: u64 = (self.buffer & ((BB::<WR>::ONE << num_bits) - BB::<WR>::ONE)).as_to();
self.bits_in_buffer -= num_bits;
self.buffer >>= num_bits;
return Ok(result);
}
let mut result: u64 = self.buffer.as_to();
let mut bits_in_res = self.bits_in_buffer;
while num_bits > Self::WORD_BITS + bits_in_res {
let new_word: u64 = self.backend.read_word()?.to_le().as_u64();
result |= new_word << bits_in_res;
bits_in_res += Self::WORD_BITS;
}
num_bits -= bits_in_res;
debug_assert!(num_bits > 0);
debug_assert!(num_bits <= Self::WORD_BITS);
let new_word = self.backend.read_word()?.to_le();
self.bits_in_buffer = Self::WORD_BITS - num_bits;
let shamt = 64 - num_bits;
let upcast: u64 = new_word.as_u64();
let final_bits: u64 = (upcast << shamt) >> shamt;
result |= final_bits << bits_in_res;
self.buffer = new_word.as_double() >> num_bits;
Ok(result)
}
#[inline]
fn read_unary(&mut self) -> Result<u64, Self::Error> {
debug_assert!(self.bits_in_buffer < Self::BUFFER_BITS);
let zeros: usize = self.buffer.trailing_zeros() as usize;
if zeros < self.bits_in_buffer {
self.buffer = self.buffer >> zeros >> 1;
self.bits_in_buffer -= zeros + 1;
return Ok(zeros as u64);
}
let mut result: u64 = self.bits_in_buffer as _;
loop {
let new_word = self.backend.read_word()?.to_le();
if new_word != WR::Word::ZERO {
let zeros: usize = new_word.trailing_zeros() as _;
self.buffer = new_word.as_double() >> zeros >> 1;
self.bits_in_buffer = Self::WORD_BITS - zeros - 1;
return Ok(result + zeros as u64);
}
result += Self::WORD_BITS as u64;
}
}
#[inline]
fn skip_bits(&mut self, mut n_bits: usize) -> Result<(), Self::Error> {
debug_assert!(self.bits_in_buffer < Self::BUFFER_BITS);
if n_bits <= self.bits_in_buffer {
self.bits_in_buffer -= n_bits;
self.buffer >>= n_bits;
return Ok(());
}
n_bits -= self.bits_in_buffer;
while n_bits > Self::WORD_BITS {
let _ = self.backend.read_word()?;
n_bits -= Self::WORD_BITS;
}
let new_word = self.backend.read_word()?.to_le();
self.bits_in_buffer = Self::WORD_BITS - n_bits;
self.buffer = new_word.as_double() >> n_bits;
Ok(())
}
#[cfg(not(feature = "no_copy_impls"))]
fn copy_to<F: Endianness, W: BitWrite<F>>(
&mut self,
bit_write: &mut W,
mut n: u64,
) -> Result<(), CopyError<Self::Error, W::Error>> {
let from_buffer = Ord::min(n, self.bits_in_buffer as _);
#[allow(unused_mut)]
let mut self_buffer_u64: u64 = self.buffer.as_to();
#[cfg(feature = "checks")]
{
if n < 64 {
self_buffer_u64 &= (1_u64 << n) - 1;
}
}
bit_write
.write_bits(self_buffer_u64, from_buffer as usize)
.map_err(CopyError::WriteError)?;
self.buffer >>= from_buffer;
n -= from_buffer;
if n == 0 {
self.bits_in_buffer -= from_buffer as usize;
return Ok(());
}
while n > Self::WORD_BITS as u64 {
bit_write
.write_bits(
self.backend
.read_word()
.map_err(CopyError::ReadError)?
.to_le()
.as_u64(),
Self::WORD_BITS,
)
.map_err(CopyError::WriteError)?;
n -= Self::WORD_BITS as u64;
}
debug_assert!(n > 0);
let new_word = self
.backend
.read_word()
.map_err(CopyError::ReadError)?
.to_le();
self.bits_in_buffer = Self::WORD_BITS - n as usize;
#[allow(unused_mut)]
let mut new_word_u64: u64 = new_word.as_u64();
#[cfg(feature = "checks")]
{
if n < 64 {
new_word_u64 &= (1_u64 << n) - 1;
}
}
bit_write
.write_bits(new_word_u64, n as usize)
.map_err(CopyError::WriteError)?;
self.buffer = new_word.as_double() >> n;
Ok(())
}
}
impl<WR: WordRead + WordSeek<Error = <WR as WordRead>::Error>, RP: ReadParams> BitSeek
for BufBitReader<LE, WR, RP>
where
WR::Word: DoubleType,
{
type Error = <WR as WordSeek>::Error;
#[inline]
fn bit_pos(&mut self) -> Result<u64, Self::Error> {
Ok(self.backend.word_pos()? * Self::WORD_BITS as u64 - self.bits_in_buffer as u64)
}
#[inline]
fn set_bit_pos(&mut self, bit_index: u64) -> Result<(), Self::Error> {
self.backend
.set_word_pos(bit_index / Self::WORD_BITS as u64)?;
let bit_offset = (bit_index % Self::WORD_BITS as u64) as usize;
self.buffer = BB::<WR>::ZERO;
self.bits_in_buffer = 0;
if bit_offset != 0 {
let new_word: BB<WR> = self.backend.read_word()?.to_le().as_double();
self.bits_in_buffer = Self::WORD_BITS - bit_offset;
self.buffer = new_word >> bit_offset;
}
Ok(())
}
}
#[cfg(feature = "std")]
impl<WR: WordRead, RP: ReadParams> std::io::Read for BufBitReader<LE, WR, RP>
where
WR::Word: DoubleType,
{
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let mut iter = buf.chunks_exact_mut(8);
for chunk in &mut iter {
let word = self
.read_bits(64)
.map_err(|_| std::io::ErrorKind::UnexpectedEof)?;
chunk.copy_from_slice(&word.to_le_bytes());
}
let rem = iter.into_remainder();
if !rem.is_empty() {
let word = self
.read_bits(rem.len() * 8)
.map_err(|_| std::io::ErrorKind::UnexpectedEof)?;
rem.copy_from_slice(&word.to_le_bytes()[..rem.len()]);
}
Ok(buf.len())
}
}
#[cfg(feature = "std")]
impl<WR: WordRead, RP: ReadParams> std::io::Read for BufBitReader<BE, WR, RP>
where
WR::Word: DoubleType,
{
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let mut iter = buf.chunks_exact_mut(8);
for chunk in &mut iter {
let word = self
.read_bits(64)
.map_err(|_| std::io::ErrorKind::UnexpectedEof)?;
chunk.copy_from_slice(&word.to_be_bytes());
}
let rem = iter.into_remainder();
if !rem.is_empty() {
let word = self
.read_bits(rem.len() * 8)
.map_err(|_| std::io::ErrorKind::UnexpectedEof)?;
rem.copy_from_slice(&word.to_be_bytes()[8 - rem.len()..]);
}
Ok(buf.len())
}
}
#[cfg(test)]
#[cfg(feature = "std")]
mod tests {
use super::*;
use crate::prelude::{MemWordReader, MemWordWriterVec};
use core::error::Error;
use std::io::Read;
#[test]
fn test_read() -> std::io::Result<()> {
let data = [
0x90, 0x2d, 0xd0, 0x26, 0xdf, 0x89, 0xbb, 0x7e, 0x3a, 0xd6, 0xc6, 0x96, 0x73, 0xe9,
0x9d, 0xc9, 0x2a, 0x77, 0x82, 0xa9, 0xe6, 0x4b, 0x53, 0xcc, 0x83, 0x80, 0x4a, 0xf3,
0xcd, 0xe3, 0x50, 0x4e, 0x45, 0x4a, 0x3a, 0x42, 0x00, 0x4b, 0x4d, 0xbe, 0x4c, 0x88,
0x24, 0xf2, 0x4b, 0x6b, 0xbd, 0x79, 0xeb, 0x74, 0xbc, 0xe8, 0x7d, 0xff, 0x4b, 0x3d,
0xa7, 0xd6, 0x0d, 0xef, 0x9c, 0x5b, 0xb3, 0xec, 0x94, 0x97, 0xcc, 0x8b, 0x41, 0xe1,
0x9c, 0xcc, 0x1a, 0x03, 0x58, 0xc4, 0xfb, 0xd0, 0xc0, 0x10, 0xe2, 0xa0, 0xc9, 0xac,
0xa7, 0xbb, 0x50, 0xf6, 0x5c, 0x87, 0x68, 0x0f, 0x42, 0x93, 0x3f, 0x2e, 0x28, 0x28,
0x76, 0x83, 0x9b, 0xeb, 0x12, 0xe0, 0x4f, 0xc5, 0xb0, 0x8d, 0x14, 0xda, 0x3b, 0xdf,
0xd3, 0x4b, 0x80, 0xd1, 0xfc, 0x87, 0x85, 0xae, 0x54, 0xc7, 0x45, 0xc9, 0x38, 0x43,
0xa7, 0x9f, 0xdd, 0xa9, 0x71, 0xa7, 0x52, 0x36, 0x82, 0xff, 0x49, 0x55, 0xdb, 0x84,
0xc2, 0x95, 0xad, 0x45, 0x80, 0xc6, 0x02, 0x80, 0xf8, 0xfc, 0x86, 0x79, 0xae, 0xb9,
0x57, 0xe7, 0x3b, 0x33, 0x64, 0xa8,
];
let data_u32 = unsafe { data.align_to::<u32>().1 };
for i in 0..data.len() {
let mut reader = BufBitReader::<LE, _>::new(MemWordReader::new_inf(&data_u32));
let mut buffer = vec![0; i];
assert_eq!(reader.read(&mut buffer)?, i);
assert_eq!(&buffer, &data[..i]);
let mut reader = BufBitReader::<BE, _>::new(MemWordReader::new_inf(&data_u32));
let mut buffer = vec![0; i];
assert_eq!(reader.read(&mut buffer)?, i);
assert_eq!(&buffer, &data[..i]);
}
Ok(())
}
macro_rules! test_buf_bit_reader {
($f: ident, $word:ty) => {
#[test]
fn $f() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
#[allow(unused_imports)]
use crate::{
codes::{GammaRead, GammaWrite},
prelude::{
BufBitWriter, DeltaRead, DeltaWrite, MemWordReader, len_delta, len_gamma,
},
};
use rand::{RngExt, SeedableRng, rngs::SmallRng};
let mut buffer_be: Vec<$word> = vec![];
let mut buffer_le: Vec<$word> = vec![];
let mut big = BufBitWriter::<BE, _>::new(MemWordWriterVec::new(&mut buffer_be));
let mut little = BufBitWriter::<LE, _>::new(MemWordWriterVec::new(&mut buffer_le));
let mut r = SmallRng::seed_from_u64(0);
const ITER: usize = 1_000_000;
for _ in 0..ITER {
let value = r.random_range(0..128);
assert_eq!(big.write_gamma(value)?, len_gamma(value));
let value = r.random_range(0..128);
assert_eq!(little.write_gamma(value)?, len_gamma(value));
let value = r.random_range(0..128);
assert_eq!(big.write_gamma(value)?, len_gamma(value));
let value = r.random_range(0..128);
assert_eq!(little.write_gamma(value)?, len_gamma(value));
let value = r.random_range(0..128);
assert_eq!(big.write_delta(value)?, len_delta(value));
let value = r.random_range(0..128);
assert_eq!(little.write_delta(value)?, len_delta(value));
let value = r.random_range(0..128);
assert_eq!(big.write_delta(value)?, len_delta(value));
let value = r.random_range(0..128);
assert_eq!(little.write_delta(value)?, len_delta(value));
let n_bits = r.random_range(0..=64);
if n_bits == 0 {
big.write_bits(0, 0)?;
} else {
big.write_bits(1, n_bits)?;
}
let n_bits = r.random_range(0..=64);
if n_bits == 0 {
little.write_bits(0, 0)?;
} else {
little.write_bits(1, n_bits)?;
}
let value = r.random_range(0..128);
assert_eq!(big.write_unary(value)?, value as usize + 1);
let value = r.random_range(0..128);
assert_eq!(little.write_unary(value)?, value as usize + 1);
}
drop(big);
drop(little);
type ReadWord = $word;
#[allow(clippy::size_of_in_element_count)] let be_trans: &[ReadWord] = unsafe {
core::slice::from_raw_parts(
buffer_be.as_ptr() as *const ReadWord,
buffer_be.len()
* (core::mem::size_of::<$word>() / core::mem::size_of::<ReadWord>()),
)
};
#[allow(clippy::size_of_in_element_count)] let le_trans: &[ReadWord] = unsafe {
core::slice::from_raw_parts(
buffer_le.as_ptr() as *const ReadWord,
buffer_le.len()
* (core::mem::size_of::<$word>() / core::mem::size_of::<ReadWord>()),
)
};
let mut big_buff = BufBitReader::<BE, _>::new(MemWordReader::new_inf(be_trans));
let mut little_buff = BufBitReader::<LE, _>::new(MemWordReader::new_inf(le_trans));
let mut r = SmallRng::seed_from_u64(0);
for _ in 0..ITER {
assert_eq!(big_buff.read_gamma()?, r.random_range(0..128));
assert_eq!(little_buff.read_gamma()?, r.random_range(0..128));
assert_eq!(big_buff.read_gamma()?, r.random_range(0..128));
assert_eq!(little_buff.read_gamma()?, r.random_range(0..128));
assert_eq!(big_buff.read_delta()?, r.random_range(0..128));
assert_eq!(little_buff.read_delta()?, r.random_range(0..128));
assert_eq!(big_buff.read_delta()?, r.random_range(0..128));
assert_eq!(little_buff.read_delta()?, r.random_range(0..128));
let n_bits = r.random_range(0..=64);
if n_bits == 0 {
assert_eq!(big_buff.read_bits(0)?, 0);
} else {
assert_eq!(big_buff.read_bits(n_bits)?, 1);
}
let n_bits = r.random_range(0..=64);
if n_bits == 0 {
assert_eq!(little_buff.read_bits(0)?, 0);
} else {
assert_eq!(little_buff.read_bits(n_bits)?, 1);
}
assert_eq!(big_buff.read_unary()?, r.random_range(0..128));
assert_eq!(little_buff.read_unary()?, r.random_range(0..128));
}
Ok(())
}
};
}
test_buf_bit_reader!(test_u64, u64);
test_buf_bit_reader!(test_u32, u32);
test_buf_bit_reader!(test_u16, u16);
}