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