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