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