1use std::cmp::min;
2use std::io;
3
4pub trait WriteBits {
5 fn align(&mut self) -> io::Result<()>;
6
7 fn write_bool_bits(&mut self, value: bool) -> io::Result<()>;
8
9 fn write_i32_bits(&mut self, bits: u32, value: i32) -> io::Result<()>;
10
11 fn write_u32_bits(&mut self, bits: u32, value: u32) -> io::Result<()>;
12
13 fn write_bytes(&mut self) -> io::Result<&mut dyn io::Write>;
15}
16
17pub struct BitsWriter<W: io::Write> {
18 bit: u32,
19 buffer: u8,
20 inner: W,
21}
22
23impl<W: io::Write> BitsWriter<W> {
24 pub fn new(inner: W) -> BitsWriter<W> {
25 BitsWriter {
26 bit: 0,
27 buffer: 0,
28 inner,
29 }
30 }
31
32 pub fn into_inner(mut self) -> io::Result<W> {
33 self.align()?;
34 Ok(self.inner)
35 }
36}
37
38impl<W: io::Write> WriteBits for BitsWriter<W> {
39 fn align(&mut self) -> io::Result<()> {
40 if self.bit != 0 {
41 self.inner.write_all(&[self.buffer])?;
42 self.bit = 0;
43 self.buffer = 0;
44 }
45 Ok(())
46 }
47
48 fn write_bool_bits(&mut self, value: bool) -> io::Result<()> {
49 debug_assert!(self.bit < 8);
50
51 if value {
52 self.buffer |= 1 << (7 - self.bit);
53 }
54 self.bit += 1;
55
56 if self.bit == 8 {
57 self.inner.write_all(&[self.buffer])?;
58 self.bit = 0;
59 self.buffer = 0;
60 }
61
62 Ok(())
63 }
64
65 fn write_i32_bits(&mut self, bits: u32, value: i32) -> io::Result<()> {
66 if value < 0 {
68 self.write_u32_bits(bits, ((1 << bits) + value) as u32)
69 } else {
70 self.write_u32_bits(bits, value as u32)
71 }
72 }
73
74 fn write_u32_bits(&mut self, mut bits: u32, value: u32) -> io::Result<()> {
75 debug_assert!(bits <= 32);
77 debug_assert!(self.bit < 8);
78
79 while bits > 0 {
80 let available_bits = 8 - self.bit;
81 let consumed_bits = min(available_bits, bits);
82 debug_assert!((1..=8).contains(&consumed_bits));
83
84 let chunk: u8 = ((value >> (bits - consumed_bits)) & ((1 << consumed_bits) - 1)) as u8;
85 self.buffer |= chunk << (available_bits - consumed_bits);
86 bits -= consumed_bits;
87 self.bit += consumed_bits;
88
89 if self.bit == 8 {
90 self.inner.write_all(&[self.buffer])?;
91 self.bit = 0;
92 self.buffer = 0;
93 }
94 }
95
96 Ok(())
97 }
98
99 fn write_bytes(&mut self) -> io::Result<&mut dyn io::Write> {
100 self.align()?;
101 Ok(&mut self.inner)
102 }
103}