rust_bitwriter/
lib.rs

1#![no_std]
2cfg_if::cfg_if! {
3    if #[cfg(feature = "std")] {
4        extern crate std;
5        use std::io::Result;
6        use std::io::{Error, ErrorKind};
7        use std::vec::Vec;
8    } else {
9        use core::result;
10        use core::fmt;
11        use core::cmp::min;
12    }
13}
14
15#[cfg(test)]
16mod tests;
17
18pub struct BitWriter {
19    // the final output
20    data: Vec<u8>,
21    bit_count: u64,
22
23    // stores unwritten bits
24    cache: u8,
25
26    // number of unwritten bits in cache
27    bits: u8,
28}
29
30impl BitWriter {
31    pub fn new() -> BitWriter {
32        BitWriter {
33            data: Vec::new(),
34            bit_count: 0,
35            cache: 0,
36            bits: 0,
37        }
38    }
39    /// Read at most 8 bits into a u8.
40    pub fn write_u8(&mut self, v: u8, bit_count: u8) -> Result<()> {
41        self.write_unsigned_bits(v as u64, bit_count, 8)
42    }
43
44    pub fn write_u16(&mut self, v: u16, bit_count: u8) -> Result<()> {
45        self.write_unsigned_bits(v as u64, bit_count, 16)
46    }
47
48    pub fn write_u32(&mut self, v: u32, bit_count: u8) -> Result<()> {
49        self.write_unsigned_bits(v as u64, bit_count, 32)
50    }
51
52    pub fn write_u64(&mut self, v: u64, bit_count: u8) -> Result<()> {
53        self.write_unsigned_bits(v, bit_count, 64)
54    }
55
56    pub fn write_i8(&mut self, v: i8, bit_count: u8) -> Result<()> {
57        self.write_signed_bits(v as i64, bit_count, 8)
58    }
59
60    pub fn write_i16(&mut self, v: i16, bit_count: u8) -> Result<()> {
61        self.write_signed_bits(v as i64, bit_count, 16)
62    }
63
64    pub fn write_i32(&mut self, v: i32, bit_count: u8) -> Result<()> {
65        self.write_signed_bits(v as i64, bit_count, 32)
66    }
67
68    pub fn write_i64(&mut self, v: i64, bit_count: u8) -> Result<()> {
69        self.write_signed_bits(v, bit_count, 64)
70    }
71
72    pub fn write_bool(&mut self, v: bool) -> Result<()> {
73        self.write_unsigned_bits(v as u64, 1, 1)
74    }
75
76    pub fn skip(&mut self, n: u64) -> Result<()> {
77        // fill the current buffer
78        for _ in 0..(n / 64) {
79            self.write_unsigned_bits(0, 64, 64)?;
80        }
81
82        let leftover = (n % 64) as u8;
83        if leftover != 0 {
84            self.write_unsigned_bits(0, leftover, 64)?;
85        }
86        Ok(())
87    }
88
89    pub fn align(&mut self, alignment_bytes: u32) -> Result<()> {
90        if alignment_bytes == 0 {
91            return Err(Error::new(
92                ErrorKind::InvalidInput,
93                "cannot align to 0 bytes",
94            ));
95        }
96        let alignment_bits = alignment_bytes as u64 * 8;
97        let cur_alignment = self.bit_count % alignment_bits;
98        let bits_to_skip = (alignment_bits - cur_alignment) % alignment_bits;
99        self.skip(bits_to_skip)
100    }
101
102    pub fn write_signed_bits(&mut self, mut v: i64, n: u8, maximum_count: u8) -> Result<()> {
103        if n == 0 {
104            return Ok(());
105        }
106        if v < 0 && n != 64 {
107            // move the sign to the correct bit position (bit_count)
108            v |= 1 << (n - 1);
109        }
110        // write as unsigned int
111        self.write_unsigned_bits(v as u64, n, maximum_count)
112    }
113
114    pub fn write_unsigned_bits(&mut self, mut v: u64, mut n: u8, maximum_count: u8) -> Result<()> {
115        if n == 0 {
116            return Ok(());
117        }
118        if n > maximum_count || n > 64 {
119            return Err(Error::new(ErrorKind::Unsupported, "too many bits to write"));
120        }
121        // mask all upper bits out to be 0
122        if n == 64 {
123            // avoid bitshift overflow exception
124            v &= u64::MAX;
125        } else {
126            v &= (1 << n) - 1;
127        }
128
129        self.bit_count += n as u64;
130
131        let new_bits = self.bits + n;
132        if new_bits < 8 {
133            // the new bits fit into the cache, no writing needed
134            self.cache |= (v as u8) << (8 - new_bits);
135            self.bits = new_bits;
136            return Ok(());
137        }
138
139        if new_bits >= 8 {
140            // write all bytes, by first taking the existing buffer, form a complete byte,
141            // and write that first.
142            let free_buffer = 8 - self.bits;
143            let new_cache = (v >> (n - free_buffer)) as u8;
144            self.data.push(self.cache | new_cache);
145            n -= free_buffer;
146
147            // Afterwards, data can be written in complete bytes
148            while n >= 8 {
149                n -= 8;
150                self.data.push((v >> n) as u8);
151            }
152        }
153
154        // Whatever is left is smaller than a byte, and will be put into the cache
155        self.cache = 0;
156        self.bits = n;
157        if n > 0 {
158            let mask = ((1 << n) as u8) - 1;
159            self.cache = ((v as u8) & mask) << (8 - n);
160        }
161        Ok(())
162    }
163
164    /// Writes a number of full bytes into the stream.
165    /// This will give best performance if the data is aligned
166    /// to a byte boundary. Otherwise, each data bytes will be
167    /// spread across two bytes in the bitstream.
168    /// Byte boundary can be ensured by using align().
169    pub fn write(&mut self, data: &Vec<u8>) -> Result<()> {
170        // If the data is byte-aligned, we can directly
171        // copy the bytes without performance penalty.
172        if self.bits == 0 {
173            // We are writing full bytes, so there is no
174            // need to update the bit count.
175            self.bit_count += 8 * data.len() as u64;
176            self.data.extend(data);
177            return Ok(());
178        }
179        // Since the buffer is not aligned, we need to
180        // bit-shift each byte.
181        for byte in data {
182            match self.write_u8(*byte, 8) {
183                Ok(()) => (),
184                Err(e) => return Err(e),
185            }
186        }
187        Ok(())
188    }
189
190    pub fn close(&mut self) -> Result<()> {
191        // align to the next byte boundary
192        self.align(1)?;
193        Ok(())
194    }
195
196    /// Returns the number of bits written so far.
197    pub fn bit_count(&self) -> u64 {
198        self.bit_count
199    }
200
201    pub fn data(&self) -> &Vec<u8> {
202        &self.data
203    }
204}