1use crate::byte_order::ByteOrder;
2use crate::error::BitReadWriteError;
3use crate::traits::BitWrite;
4use std::io::{BufWriter, Result, Write};
5
6pub struct BitWriter<W: Write> {
7 byte_order: ByteOrder,
8 inner: Option<BufWriter<W>>, bits_buffer: u64,
11 bits_in_buffer: usize,
12}
13
14impl<W: Write> BitWriter<W> {
15 pub fn new(inner: W) -> Self {
16 Self::with_byte_order(ByteOrder::BigEndian, inner)
17 }
18
19 pub fn with_byte_order(byte_order: ByteOrder, inner: W) -> Self {
20 Self {
21 byte_order,
22 inner: Option::from(BufWriter::new(inner)),
23 bits_buffer: 0,
24 bits_in_buffer: 0,
25 }
26 }
27}
28
29impl<W: Write> BitWriter<W> {
30 fn inner_mut(&mut self) -> Result<&mut BufWriter<W>> {
31 self.inner
32 .as_mut()
33 .ok_or_else(|| std::io::Error::new(std::io::ErrorKind::Other, "inner writer is gone"))
34 }
35}
36
37impl<W: Write> BitWriter<W> {
38 fn write_aligned_bytes_to_inner(&mut self) -> Result<()> {
40 let count = self.bits_in_buffer / 8;
43 if count == 0 {
44 return Ok(());
45 }
46
47 let mut buf = Vec::with_capacity(count);
48 for _ in 0..count {
49 let byte = match self.byte_order {
50 ByteOrder::BigEndian => (self.bits_buffer >> 56) as u8, ByteOrder::LittleEndian => self.bits_buffer as u8, };
53 buf.push(byte);
54
55 match self.byte_order {
56 ByteOrder::BigEndian => {
57 self.bits_buffer <<= 8; }
59 ByteOrder::LittleEndian => {
60 self.bits_buffer >>= 8; }
62 }
63 self.bits_in_buffer -= 8; }
65 self.inner_mut()?.write_all(&buf)?; Ok(())
67 }
68
69 fn write_residual_partial_byte_to_inner(&mut self) -> Result<()> {
71 if self.bits_in_buffer > 0 && self.bits_in_buffer < 8 {
72 let byte = match self.byte_order {
73 ByteOrder::BigEndian => (self.bits_buffer >> 56) as u8, ByteOrder::LittleEndian => self.bits_buffer as u8, };
76 self.inner_mut()?.write_all(&[byte])?;
77 self.bits_buffer = 0; self.bits_in_buffer = 0; }
80 Ok(())
81 }
82}
83
84impl<W: Write> BitWriter<W> {
85 pub fn into_inner(mut self) -> Result<W> {
86 self.write_residual_partial_byte_to_inner()?;
87 if let Some(mut inner) = self.inner.take() {
88 inner.flush()?;
89 inner.into_inner().map_err(|e| e.into_error())
90 } else {
91 Err(std::io::Error::new(
93 std::io::ErrorKind::Other,
94 "inner already taken",
95 ))
96 }
97 }
98}
99
100impl<W: Write> Write for BitWriter<W> {
101 fn write(&mut self, buf: &[u8]) -> Result<usize> {
102 self.write_aligned_bytes_to_inner()?;
104
105 if self.bits_in_buffer == 0 {
106 self.inner_mut()?.write(buf)?;
108 return Ok(buf.len());
109 }
110
111 for &b in buf {
113 self.write_bits(b as u64, 8)?;
114 }
115
116 Ok(buf.len())
117 }
118
119 fn flush(&mut self) -> Result<()> {
120 self.write_residual_partial_byte_to_inner()?;
122 self.inner_mut()?.flush()
123 }
124}
125
126impl<W: Write> Drop for BitWriter<W> {
127 fn drop(&mut self) {
128 let _ = self.write_residual_partial_byte_to_inner();
131
132 if let Some(ref mut inner) = self.inner {
134 let _ = inner.flush();
135 }
136 }
138}
139
140impl<W: Write> BitWrite for BitWriter<W> {
141 fn write_bits(&mut self, value: u64, n: usize) -> Result<()> {
142 if n == 0 || n > 64 {
144 return Err(BitReadWriteError::InvalidBitCount(n).into());
145 }
146
147 let mut remaining = n;
148 let mask = if n == 64 { u64::MAX } else { (1u64 << n) - 1 }; let mut val = value & mask; while remaining > 0 {
152 let available = 64 - self.bits_in_buffer;
153 let to_insert = remaining.min(available);
154 let insert_at_next_round = remaining - to_insert;
155 let to_insert_val = val >> insert_at_next_round; match self.byte_order {
158 ByteOrder::BigEndian => {
159 self.bits_buffer |= to_insert_val << (available - to_insert); }
161 ByteOrder::LittleEndian => {
162 self.bits_buffer |= to_insert_val << self.bits_in_buffer; }
164 }
165
166 self.bits_in_buffer += to_insert; remaining -= to_insert; if insert_at_next_round > 0 {
170 val &= (1u64 << insert_at_next_round) - 1; }
172
173 if self.bits_in_buffer >= 8 || remaining == 0 {
175 self.write_aligned_bytes_to_inner()?; }
177 }
178
179 Ok(())
180 }
181}