1use core::any::TypeId;
10use core::{mem, ptr};
11
12use crate::codes::params::{DefaultWriteParams, WriteParams};
13use crate::traits::*;
14#[cfg(feature = "mem_dbg")]
15use mem_dbg::{MemDbg, MemSize};
16use num_primitive::{PrimitiveInteger, PrimitiveNumber, PrimitiveNumberAs};
17
18#[derive(Debug)]
44#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
45pub struct BufBitWriter<E: Endianness, WW: WordWrite, WP: WriteParams = DefaultWriteParams> {
46 backend: WW,
48 buffer: WW::Word,
53 space_left_in_buffer: usize,
55 _marker: core::marker::PhantomData<(E, WP)>,
56}
57
58#[cfg(feature = "std")]
73pub fn from_path<E: Endianness, W: Word>(
74 path: impl AsRef<std::path::Path>,
75) -> std::io::Result<
76 BufBitWriter<E, super::WordAdapter<W, std::io::BufWriter<std::fs::File>>, DefaultWriteParams>,
77>
78where
79 W::Bytes: AsRef<[u8]>,
80{
81 Ok(from_file::<E, W>(std::fs::File::create(path)?))
82}
83
84#[must_use]
90#[cfg(feature = "std")]
91pub fn from_file<E: Endianness, W: Word>(
92 file: std::fs::File,
93) -> BufBitWriter<E, super::WordAdapter<W, std::io::BufWriter<std::fs::File>>, DefaultWriteParams>
94where
95 W::Bytes: AsRef<[u8]>,
96{
97 BufBitWriter::<E, super::WordAdapter<W, std::io::BufWriter<std::fs::File>>>::new(
98 super::WordAdapter::new(std::io::BufWriter::new(file)),
99 )
100}
101
102impl<E: Endianness, WW: WordWrite, WP: WriteParams> BufBitWriter<E, WW, WP> {
103 const WORD_BITS: usize = WW::Word::BITS as usize;
104
105 #[must_use]
120 pub const fn new(backend: WW) -> Self {
121 Self {
122 backend,
123 buffer: WW::Word::ZERO,
124 space_left_in_buffer: Self::WORD_BITS,
125 _marker: core::marker::PhantomData,
126 }
127 }
128}
129
130impl<E: Endianness, WW: WordWrite + Default, WP: WriteParams> Default for BufBitWriter<E, WW, WP>
131where
132 BufBitWriter<E, WW, WP>: BitWrite<E>,
133{
134 fn default() -> Self {
135 Self::new(WW::default())
136 }
137}
138
139impl<E: Endianness, WW: WordWrite, WP: WriteParams> BufBitWriter<E, WW, WP>
140where
141 BufBitWriter<E, WW, WP>: BitWrite<E>,
142{
143 pub fn into_inner(mut self) -> Result<WW, <Self as BitWrite<E>>::Error> {
146 self.flush()?;
147 let backend = unsafe { ptr::read(&self.backend) };
149 mem::forget(self);
150 Ok(backend)
151 }
152}
153
154impl<E: Endianness, WW: WordWrite, WP: WriteParams> core::ops::Drop for BufBitWriter<E, WW, WP> {
155 fn drop(&mut self) {
156 if TypeId::of::<E>() == TypeId::of::<LE>() {
157 flush_le(self).unwrap();
158 } else {
159 flush_be(self).unwrap();
161 }
162 }
163}
164
165fn flush_be<E: Endianness, WW: WordWrite, WP: WriteParams>(
171 buf_bit_writer: &mut BufBitWriter<E, WW, WP>,
172) -> Result<usize, WW::Error> {
173 let to_flush = WW::Word::BITS as usize - buf_bit_writer.space_left_in_buffer;
174 if to_flush != 0 {
175 buf_bit_writer.buffer <<= buf_bit_writer.space_left_in_buffer;
176 buf_bit_writer
177 .backend
178 .write_word(buf_bit_writer.buffer.to_be())?;
179 buf_bit_writer.space_left_in_buffer = WW::Word::BITS as usize;
180 }
181 buf_bit_writer.backend.flush()?;
182 Ok(to_flush)
183}
184
185impl<WW: WordWrite, WP: WriteParams> BitWrite<BE> for BufBitWriter<BE, WW, WP>
186where
187 u64: PrimitiveNumberAs<WW::Word>,
188{
189 type Error = <WW as WordWrite>::Error;
190
191 fn flush(&mut self) -> Result<usize, Self::Error> {
192 flush_be(self)
193 }
194
195 #[allow(unused_mut)]
196 #[inline(always)]
197 fn write_bits(&mut self, mut value: u64, num_bits: usize) -> Result<usize, Self::Error> {
198 debug_assert!(num_bits <= 64);
199 #[cfg(feature = "checks")]
200 assert!(
201 value & (1_u128 << num_bits).wrapping_sub(1) as u64 == value,
202 "Error: value {} does not fit in {} bits",
203 value,
204 num_bits
205 );
206 debug_assert!(self.space_left_in_buffer > 0);
207
208 #[cfg(test)]
209 if num_bits < 64 {
210 value |= u64::MAX << num_bits;
212 }
213
214 if num_bits < self.space_left_in_buffer {
216 self.buffer <<= num_bits;
217 self.buffer |= value.as_to() & !(WW::Word::MAX << num_bits as u32);
219 self.space_left_in_buffer -= num_bits;
220 return Ok(num_bits);
221 }
222
223 self.buffer = self.buffer << (self.space_left_in_buffer - 1) << 1;
225 self.buffer |= (value << (64 - num_bits) >> (64 - self.space_left_in_buffer)).as_to();
227 self.backend.write_word(self.buffer.to_be())?;
228
229 let mut to_write = num_bits - self.space_left_in_buffer;
230
231 for _ in 0..to_write / (Self::WORD_BITS) {
232 to_write -= Self::WORD_BITS;
233 self.backend
234 .write_word((value >> to_write).as_to().to_be())?;
235 }
236
237 self.space_left_in_buffer = Self::WORD_BITS - to_write;
238 self.buffer = value.as_to();
239 Ok(num_bits)
240 }
241
242 #[inline(always)]
243 #[allow(clippy::collapsible_if)]
244 fn write_unary(&mut self, mut n: u64) -> Result<usize, Self::Error> {
245 debug_assert!(n < u64::MAX);
246 debug_assert!(self.space_left_in_buffer > 0);
247
248 let code_length = n + 1;
249
250 if code_length <= self.space_left_in_buffer as u64 {
252 self.space_left_in_buffer -= code_length as usize;
253 self.buffer = self.buffer << n << 1;
254 self.buffer |= WW::Word::ONE;
255 if self.space_left_in_buffer == 0 {
256 self.backend.write_word(self.buffer.to_be())?;
257 self.space_left_in_buffer = Self::WORD_BITS;
258 }
259 return Ok(code_length as usize);
260 }
261
262 self.buffer = self.buffer << (self.space_left_in_buffer - 1) << 1;
263 self.backend.write_word(self.buffer.to_be())?;
264
265 n -= self.space_left_in_buffer as u64;
266
267 for _ in 0..n / WW::Word::BITS as u64 {
268 self.backend.write_word(WW::Word::ZERO)?;
269 }
270
271 n %= WW::Word::BITS as u64;
272
273 if n == WW::Word::BITS as u64 - 1 {
274 self.backend.write_word(WW::Word::ONE.to_be())?;
275 self.space_left_in_buffer = Self::WORD_BITS;
276 } else {
277 self.buffer = WW::Word::ONE;
278 self.space_left_in_buffer = Self::WORD_BITS - (n as usize + 1);
279 }
280
281 Ok(code_length as usize)
282 }
283
284 #[cfg(not(feature = "no_copy_impls"))]
285 fn copy_from<F: Endianness, R: BitRead<F>>(
286 &mut self,
287 bit_read: &mut R,
288 mut n: u64,
289 ) -> Result<(), CopyError<R::Error, Self::Error>> {
290 if n < self.space_left_in_buffer as u64 {
291 self.buffer = (self.buffer << n)
292 | bit_read
293 .read_bits(n as usize)
294 .map_err(CopyError::ReadError)?
295 .as_to();
296 self.space_left_in_buffer -= n as usize;
297 return Ok(());
298 }
299
300 self.buffer = (self.buffer << (self.space_left_in_buffer - 1) << 1)
301 | bit_read
302 .read_bits(self.space_left_in_buffer)
303 .map_err(CopyError::ReadError)?
304 .as_to();
305 n -= self.space_left_in_buffer as u64;
306
307 self.backend
308 .write_word(self.buffer.to_be())
309 .map_err(CopyError::WriteError)?;
310
311 for _ in 0..n / WW::Word::BITS as u64 {
312 self.backend
313 .write_word(
314 bit_read
315 .read_bits(Self::WORD_BITS)
316 .map_err(CopyError::ReadError)?
317 .as_to()
318 .to_be(),
319 )
320 .map_err(CopyError::WriteError)?;
321 }
322
323 n %= WW::Word::BITS as u64;
324 self.buffer = bit_read
325 .read_bits(n as usize)
326 .map_err(CopyError::ReadError)?
327 .as_to();
328 self.space_left_in_buffer = Self::WORD_BITS - n as usize;
329
330 Ok(())
331 }
332}
333
334fn flush_le<E: Endianness, WW: WordWrite, WP: WriteParams>(
340 buf_bit_writer: &mut BufBitWriter<E, WW, WP>,
341) -> Result<usize, WW::Error> {
342 let to_flush = WW::Word::BITS as usize - buf_bit_writer.space_left_in_buffer;
343 if to_flush != 0 {
344 buf_bit_writer.buffer >>= buf_bit_writer.space_left_in_buffer;
345 buf_bit_writer
346 .backend
347 .write_word(buf_bit_writer.buffer.to_le())?;
348 buf_bit_writer.space_left_in_buffer = WW::Word::BITS as usize;
349 }
350 buf_bit_writer.backend.flush()?;
351 Ok(to_flush)
352}
353
354impl<WW: WordWrite, WP: WriteParams> BitWrite<LE> for BufBitWriter<LE, WW, WP>
355where
356 u64: PrimitiveNumberAs<WW::Word>,
357{
358 type Error = <WW as WordWrite>::Error;
359
360 fn flush(&mut self) -> Result<usize, Self::Error> {
361 flush_le(self)
362 }
363
364 #[inline(always)]
365 fn write_bits(&mut self, mut value: u64, num_bits: usize) -> Result<usize, Self::Error> {
366 debug_assert!(num_bits <= 64);
367 #[cfg(feature = "checks")]
368 assert!(
369 value & (1_u128 << num_bits).wrapping_sub(1) as u64 == value,
370 "Error: value {} does not fit in {} bits",
371 value,
372 num_bits
373 );
374 debug_assert!(self.space_left_in_buffer > 0);
375
376 #[cfg(test)]
377 if num_bits < 64 {
378 value |= u64::MAX << num_bits;
380 }
381
382 if num_bits < self.space_left_in_buffer {
384 self.buffer >>= num_bits;
385 self.buffer |=
387 (value.as_to() & !(WW::Word::MAX << num_bits as u32)).rotate_right(num_bits as u32);
388 self.space_left_in_buffer -= num_bits;
389 return Ok(num_bits);
390 }
391
392 self.buffer = self.buffer >> (self.space_left_in_buffer - 1) >> 1;
394 self.buffer |= value.as_to() << (Self::WORD_BITS - self.space_left_in_buffer);
395 self.backend.write_word(self.buffer.to_le())?;
396
397 let to_write = num_bits - self.space_left_in_buffer;
398 value = value >> (self.space_left_in_buffer - 1) >> 1;
399
400 for _ in 0..to_write / (Self::WORD_BITS) {
401 self.backend.write_word(value.as_to().to_le())?;
402 value >>= WW::Word::BITS;
404 }
405
406 self.space_left_in_buffer = Self::WORD_BITS - to_write % (Self::WORD_BITS);
407 self.buffer = value.as_to().rotate_right(to_write as u32);
408 Ok(num_bits)
409 }
410
411 #[inline(always)]
412 #[allow(clippy::collapsible_if)]
413 fn write_unary(&mut self, mut n: u64) -> Result<usize, Self::Error> {
414 debug_assert!(n < u64::MAX);
415 debug_assert!(self.space_left_in_buffer > 0);
416
417 let code_length = n + 1;
418
419 if code_length <= self.space_left_in_buffer as u64 {
421 self.space_left_in_buffer -= code_length as usize;
422 self.buffer = self.buffer >> n >> 1;
423 self.buffer |= WW::Word::ONE << (Self::WORD_BITS - 1);
424 if self.space_left_in_buffer == 0 {
425 self.backend.write_word(self.buffer.to_le())?;
426 self.space_left_in_buffer = Self::WORD_BITS;
427 }
428 return Ok(code_length as usize);
429 }
430
431 self.buffer = self.buffer >> (self.space_left_in_buffer - 1) >> 1;
432 self.backend.write_word(self.buffer.to_le())?;
433
434 n -= self.space_left_in_buffer as u64;
435
436 for _ in 0..n / WW::Word::BITS as u64 {
437 self.backend.write_word(WW::Word::ZERO)?;
438 }
439
440 n %= WW::Word::BITS as u64;
441
442 if n == WW::Word::BITS as u64 - 1 {
443 self.backend
444 .write_word((WW::Word::ONE << (Self::WORD_BITS - 1)).to_le())?;
445 self.space_left_in_buffer = Self::WORD_BITS;
446 } else {
447 self.buffer = WW::Word::ONE << (Self::WORD_BITS - 1);
448 self.space_left_in_buffer = Self::WORD_BITS - (n as usize + 1);
449 }
450
451 Ok(code_length as usize)
452 }
453
454 #[cfg(not(feature = "no_copy_impls"))]
455 fn copy_from<F: Endianness, R: BitRead<F>>(
456 &mut self,
457 bit_read: &mut R,
458 mut n: u64,
459 ) -> Result<(), CopyError<R::Error, Self::Error>> {
460 if n < self.space_left_in_buffer as u64 {
461 self.buffer = (self.buffer >> n)
462 | (bit_read
463 .read_bits(n as usize)
464 .map_err(CopyError::ReadError)?)
465 .as_to()
466 .rotate_right(n as u32);
467 self.space_left_in_buffer -= n as usize;
468 return Ok(());
469 }
470
471 self.buffer = (self.buffer >> (self.space_left_in_buffer - 1) >> 1)
472 | (bit_read
473 .read_bits(self.space_left_in_buffer)
474 .map_err(CopyError::ReadError)?
475 .as_to())
476 .rotate_right(self.space_left_in_buffer as u32);
477 n -= self.space_left_in_buffer as u64;
478
479 self.backend
480 .write_word(self.buffer.to_le())
481 .map_err(CopyError::WriteError)?;
482
483 for _ in 0..n / WW::Word::BITS as u64 {
484 self.backend
485 .write_word(
486 bit_read
487 .read_bits(Self::WORD_BITS)
488 .map_err(CopyError::ReadError)?
489 .as_to()
490 .to_le(),
491 )
492 .map_err(CopyError::WriteError)?;
493 }
494
495 n %= WW::Word::BITS as u64;
496 self.buffer = bit_read
497 .read_bits(n as usize)
498 .map_err(CopyError::ReadError)?
499 .as_to()
500 .rotate_right(n as u32);
501 self.space_left_in_buffer = Self::WORD_BITS - n as usize;
502
503 Ok(())
504 }
505}
506
507#[cfg(feature = "std")]
508impl<WW: WordWrite, WP: WriteParams> std::io::Write for BufBitWriter<BE, WW, WP>
509where
510 u64: PrimitiveNumberAs<WW::Word>,
511{
512 #[inline(always)]
513 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
514 let mut iter = buf.chunks_exact(8);
515
516 for word in &mut iter {
517 self.write_bits(u64::from_be_bytes(word.try_into().unwrap()), 64)
518 .map_err(|_| std::io::Error::other("could not write bits to stream"))?;
519 }
520
521 let rem = iter.remainder();
522 if !rem.is_empty() {
523 let mut word = 0;
524 let bits = rem.len() * 8;
525 for byte in rem.iter() {
526 word <<= 8;
527 word |= *byte as u64;
528 }
529 self.write_bits(word, bits)
530 .map_err(|_| std::io::Error::other("could not write bits to stream"))?;
531 }
532
533 Ok(buf.len())
534 }
535
536 fn flush(&mut self) -> std::io::Result<()> {
537 flush_be(self).map_err(|_| std::io::Error::other("could not flush bits to stream"))?;
538 Ok(())
539 }
540}
541
542#[cfg(feature = "std")]
543impl<WW: WordWrite, WP: WriteParams> std::io::Write for BufBitWriter<LE, WW, WP>
544where
545 u64: PrimitiveNumberAs<WW::Word>,
546{
547 #[inline(always)]
548 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
549 let mut iter = buf.chunks_exact(8);
550
551 for word in &mut iter {
552 self.write_bits(u64::from_le_bytes(word.try_into().unwrap()), 64)
553 .map_err(|_| std::io::Error::other("could not write bits to stream"))?;
554 }
555
556 let rem = iter.remainder();
557 if !rem.is_empty() {
558 let mut word = 0;
559 let bits = rem.len() * 8;
560 for byte in rem.iter().rev() {
561 word <<= 8;
562 word |= *byte as u64;
563 }
564 self.write_bits(word, bits)
565 .map_err(|_| std::io::Error::other("could not write bits to stream"))?;
566 }
567
568 Ok(buf.len())
569 }
570
571 fn flush(&mut self) -> std::io::Result<()> {
572 flush_le(self).map_err(|_| std::io::Error::other("could not flush bits to stream"))?;
573 Ok(())
574 }
575}
576
577#[cfg(test)]
578#[cfg(feature = "std")]
579mod tests {
580 use super::*;
581 use crate::prelude::MemWordWriterVec;
582 use std::io::Write;
583
584 #[test]
585 fn test_write() -> Result<(), Box<dyn core::error::Error>> {
586 let data = [
587 0x90, 0x2d, 0xd0, 0x26, 0xdf, 0x89, 0xbb, 0x7e, 0x3a, 0xd6, 0xc6, 0x96, 0x73, 0xe9,
588 0x9d, 0xc9, 0x2a, 0x77, 0x82, 0xa9, 0xe6, 0x4b, 0x53, 0xcc, 0x83, 0x80, 0x4a, 0xf3,
589 0xcd, 0xe3, 0x50, 0x4e, 0x45, 0x4a, 0x3a, 0x42, 0x00, 0x4b, 0x4d, 0xbe, 0x4c, 0x88,
590 0x24, 0xf2, 0x4b, 0x6b, 0xbd, 0x79, 0xeb, 0x74, 0xbc, 0xe8, 0x7d, 0xff, 0x4b, 0x3d,
591 0xa7, 0xd6, 0x0d, 0xef, 0x9c, 0x5b, 0xb3, 0xec, 0x94, 0x97, 0xcc, 0x8b, 0x41, 0xe1,
592 0x9c, 0xcc, 0x1a, 0x03, 0x58, 0xc4, 0xfb, 0xd0, 0xc0, 0x10, 0xe2, 0xa0, 0xc9, 0xac,
593 0xa7, 0xbb, 0x50, 0xf6, 0x5c, 0x87, 0x68, 0x0f, 0x42, 0x93, 0x3f, 0x2e, 0x28, 0x28,
594 0x76, 0x83, 0x9b, 0xeb, 0x12, 0xe0, 0x4f, 0xc5, 0xb0, 0x8d, 0x14, 0xda, 0x3b, 0xdf,
595 0xd3, 0x4b, 0x80, 0xd1, 0xfc, 0x87, 0x85, 0xae, 0x54, 0xc7, 0x45, 0xc9, 0x38, 0x43,
596 0xa7, 0x9f, 0xdd, 0xa9, 0x71, 0xa7, 0x52, 0x36, 0x82, 0xff, 0x49, 0x55, 0xdb, 0x84,
597 0xc2, 0x95, 0xad, 0x45, 0x80, 0xc6, 0x02, 0x80, 0xf8, 0xfc, 0x86, 0x79, 0xae, 0xb9,
598 0x57, 0xe7, 0x3b, 0x33, 0x64, 0xa8,
599 ];
600
601 for i in 0..data.len() {
602 let mut buffer = Vec::<u64>::new();
603 let mut writer = BufBitWriter::<BE, _>::new(MemWordWriterVec::new(&mut buffer));
604
605 writer.write_all(&data[..i])?;
606 std::io::Write::flush(&mut writer)?;
607
608 let buffer = writer.into_inner()?.into_inner();
609 assert_eq!(unsafe { &buffer.align_to::<u8>().1[..i] }, &data[..i]);
610
611 let mut buffer = Vec::<u64>::new();
612 let mut writer = BufBitWriter::<LE, _>::new(MemWordWriterVec::new(&mut buffer));
613
614 writer.write_all(&data[..i])?;
615 std::io::Write::flush(&mut writer)?;
616
617 let buffer = writer.into_inner()?.into_inner();
618 assert_eq!(unsafe { &buffer.align_to::<u8>().1[..i] }, &data[..i]);
619 }
620 Ok(())
621 }
622
623 macro_rules! test_buf_bit_writer {
624 ($f: ident, $word:ty) => {
625 #[test]
626 fn $f() -> Result<(), Box<dyn core::error::Error + Send + Sync + 'static>> {
627 #[allow(unused_imports)]
628 use crate::{
629 codes::{GammaRead, GammaWrite},
630 prelude::{
631 BufBitReader, DeltaRead, DeltaWrite, MemWordReader, len_delta, len_gamma,
632 },
633 };
634
635 use rand::{RngExt, SeedableRng, rngs::SmallRng};
636
637 let mut buffer_be: Vec<$word> = vec![];
638 let mut buffer_le: Vec<$word> = vec![];
639 let mut big = BufBitWriter::<BE, _>::new(MemWordWriterVec::new(&mut buffer_be));
640 let mut little = BufBitWriter::<LE, _>::new(MemWordWriterVec::new(&mut buffer_le));
641
642 let mut r = SmallRng::seed_from_u64(0);
643 const ITER: usize = 1_000_000;
644
645 for _ in 0..ITER {
646 let value = r.random_range(0..128);
647 assert_eq!(big.write_gamma(value)?, len_gamma(value));
648 let value = r.random_range(0..128);
649 assert_eq!(little.write_gamma(value)?, len_gamma(value));
650 let value = r.random_range(0..128);
651 assert_eq!(big.write_gamma(value)?, len_gamma(value));
652 let value = r.random_range(0..128);
653 assert_eq!(little.write_gamma(value)?, len_gamma(value));
654 let value = r.random_range(0..128);
655 assert_eq!(big.write_delta(value)?, len_delta(value));
656 let value = r.random_range(0..128);
657 assert_eq!(little.write_delta(value)?, len_delta(value));
658 let value = r.random_range(0..128);
659 assert_eq!(big.write_delta(value)?, len_delta(value));
660 let value = r.random_range(0..128);
661 assert_eq!(little.write_delta(value)?, len_delta(value));
662 let n_bits = r.random_range(0..=64);
663 if n_bits == 0 {
664 big.write_bits(0, 0)?;
665 } else {
666 big.write_bits(r.random::<u64>() & u64::MAX >> 64 - n_bits, n_bits)?;
667 }
668 let n_bits = r.random_range(0..=64);
669 if n_bits == 0 {
670 little.write_bits(0, 0)?;
671 } else {
672 little.write_bits(r.random::<u64>() & u64::MAX >> 64 - n_bits, n_bits)?;
673 }
674 let value = r.random_range(0..128);
675 assert_eq!(big.write_unary(value)?, value as usize + 1);
676 let value = r.random_range(0..128);
677 assert_eq!(little.write_unary(value)?, value as usize + 1);
678 }
679
680 drop(big);
681 drop(little);
682
683 type ReadWord = u16;
684 #[allow(clippy::size_of_in_element_count)] let be_trans: &[ReadWord] = unsafe {
686 core::slice::from_raw_parts(
687 buffer_be.as_ptr() as *const ReadWord,
688 buffer_be.len()
689 * (core::mem::size_of::<$word>() / core::mem::size_of::<ReadWord>()),
690 )
691 };
692 #[allow(clippy::size_of_in_element_count)] let le_trans: &[ReadWord] = unsafe {
694 core::slice::from_raw_parts(
695 buffer_le.as_ptr() as *const ReadWord,
696 buffer_le.len()
697 * (core::mem::size_of::<$word>() / core::mem::size_of::<ReadWord>()),
698 )
699 };
700
701 let mut big_buff = BufBitReader::<BE, _>::new(MemWordReader::new_inf(be_trans));
702 let mut little_buff = BufBitReader::<LE, _>::new(MemWordReader::new_inf(le_trans));
703
704 let mut r = SmallRng::seed_from_u64(0);
705
706 for _ in 0..ITER {
707 assert_eq!(big_buff.read_gamma()?, r.random_range(0..128));
708 assert_eq!(little_buff.read_gamma()?, r.random_range(0..128));
709 assert_eq!(big_buff.read_gamma()?, r.random_range(0..128));
710 assert_eq!(little_buff.read_gamma()?, r.random_range(0..128));
711 assert_eq!(big_buff.read_delta()?, r.random_range(0..128));
712 assert_eq!(little_buff.read_delta()?, r.random_range(0..128));
713 assert_eq!(big_buff.read_delta()?, r.random_range(0..128));
714 assert_eq!(little_buff.read_delta()?, r.random_range(0..128));
715 let n_bits = r.random_range(0..=64);
716 if n_bits == 0 {
717 assert_eq!(big_buff.read_bits(0)?, 0);
718 } else {
719 assert_eq!(
720 big_buff.read_bits(n_bits)?,
721 r.random::<u64>() & u64::MAX >> 64 - n_bits
722 );
723 }
724 let n_bits = r.random_range(0..=64);
725 if n_bits == 0 {
726 assert_eq!(little_buff.read_bits(0)?, 0);
727 } else {
728 assert_eq!(
729 little_buff.read_bits(n_bits)?,
730 r.random::<u64>() & u64::MAX >> 64 - n_bits
731 );
732 }
733
734 assert_eq!(big_buff.read_unary()?, r.random_range(0..128));
735 assert_eq!(little_buff.read_unary()?, r.random_range(0..128));
736 }
737
738 Ok(())
739 }
740 };
741 }
742
743 test_buf_bit_writer!(test_u128, u128);
744 test_buf_bit_writer!(test_u64, u64);
745 test_buf_bit_writer!(test_u32, u32);
746
747 test_buf_bit_writer!(test_u16, u16);
748 test_buf_bit_writer!(test_usize, usize);
749}