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