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