Skip to main content

oximedia_codec/
bitstream_writer.rs

1//! Bitstream reading and writing utilities.
2//!
3//! Provides bit-level access to byte buffers, supporting arbitrary-width
4//! field reads and writes as used in video codec bitstream parsing.
5
6// -------------------------------------------------------------------------
7// BitstreamWriter
8// -------------------------------------------------------------------------
9
10/// Writes individual bits or multi-bit fields into a byte buffer.
11///
12/// Bits are packed MSB-first within each byte.  Call [`flush`](Self::flush)
13/// to finalise and retrieve the completed buffer.
14#[derive(Debug, Clone)]
15#[allow(dead_code)]
16pub struct BitstreamWriter {
17    /// Completed bytes.
18    buffer: Vec<u8>,
19    /// Position of the next bit to write within `current_byte` (0 = MSB, 7 = LSB).
20    bit_pos: u8,
21    /// Byte being assembled; pushed to `buffer` when full.
22    current_byte: u8,
23}
24
25impl BitstreamWriter {
26    /// Creates an empty `BitstreamWriter`.
27    #[allow(dead_code)]
28    pub fn new() -> Self {
29        Self {
30            buffer: Vec::new(),
31            bit_pos: 0,
32            current_byte: 0,
33        }
34    }
35
36    /// Writes a single bit.  `true` → 1, `false` → 0.
37    #[allow(dead_code)]
38    pub fn write_bit(&mut self, bit: bool) {
39        if bit {
40            self.current_byte |= 0x80 >> self.bit_pos;
41        }
42        self.bit_pos += 1;
43        if self.bit_pos == 8 {
44            self.buffer.push(self.current_byte);
45            self.current_byte = 0;
46            self.bit_pos = 0;
47        }
48    }
49
50    /// Writes the lowest `count` bits of `value`, most-significant bit first.
51    ///
52    /// `count` must be in `1..=64`.
53    #[allow(dead_code)]
54    pub fn write_bits(&mut self, value: u64, count: u8) {
55        assert!(count > 0 && count <= 64, "count must be in 1..=64");
56        for i in (0..count).rev() {
57            let bit = (value >> i) & 1 == 1;
58            self.write_bit(bit);
59        }
60    }
61
62    /// Writes all 8 bits of `byte`, MSB first.
63    #[allow(dead_code)]
64    pub fn write_byte(&mut self, byte: u8) {
65        self.write_bits(u64::from(byte), 8);
66    }
67
68    /// Flushes any partially-assembled byte (zero-padded on the LSB side)
69    /// and returns the completed buffer.
70    #[allow(dead_code)]
71    pub fn flush(mut self) -> Vec<u8> {
72        if self.bit_pos > 0 {
73            self.buffer.push(self.current_byte);
74        }
75        self.buffer
76    }
77
78    /// Returns the total number of bits written so far (including bits in the
79    /// current partial byte).
80    #[allow(dead_code)]
81    pub fn bits_written(&self) -> u64 {
82        self.buffer.len() as u64 * 8 + u64::from(self.bit_pos)
83    }
84
85    /// Returns the number of complete bytes in the buffer (excluding any
86    /// partial byte currently being assembled).
87    #[allow(dead_code)]
88    pub fn bytes_used(&self) -> usize {
89        self.buffer.len()
90    }
91}
92
93// -------------------------------------------------------------------------
94// BitstreamReader
95// -------------------------------------------------------------------------
96
97/// Reads individual bits or multi-bit fields from a byte slice.
98///
99/// Bits are extracted MSB-first from each byte, matching the write order of
100/// [`BitstreamWriter`].
101#[derive(Debug, Clone)]
102#[allow(dead_code)]
103pub struct BitstreamReader {
104    /// The underlying data.
105    data: Vec<u8>,
106    /// Index of the byte currently being read.
107    byte_pos: usize,
108    /// Bit position within the current byte (0 = MSB).
109    bit_pos: u8,
110}
111
112impl BitstreamReader {
113    /// Creates a `BitstreamReader` over the given data.
114    #[allow(dead_code)]
115    pub fn new(data: Vec<u8>) -> Self {
116        Self {
117            data,
118            byte_pos: 0,
119            bit_pos: 0,
120        }
121    }
122
123    /// Reads a single bit, returning `None` when the buffer is exhausted.
124    #[allow(dead_code)]
125    pub fn read_bit(&mut self) -> Option<bool> {
126        if self.byte_pos >= self.data.len() {
127            return None;
128        }
129        let byte = self.data[self.byte_pos];
130        let bit = (byte >> (7 - self.bit_pos)) & 1 == 1;
131        self.bit_pos += 1;
132        if self.bit_pos == 8 {
133            self.byte_pos += 1;
134            self.bit_pos = 0;
135        }
136        Some(bit)
137    }
138
139    /// Reads `count` bits (MSB first) and assembles them into a `u64`.
140    ///
141    /// Returns `None` if there are fewer than `count` bits remaining.
142    /// `count` must be in `1..=64`.
143    #[allow(dead_code)]
144    pub fn read_bits(&mut self, count: u8) -> Option<u64> {
145        assert!(count > 0 && count <= 64, "count must be in 1..=64");
146        let mut value: u64 = 0;
147        for _ in 0..count {
148            let bit = self.read_bit()?;
149            value = (value << 1) | u64::from(bit);
150        }
151        Some(value)
152    }
153
154    /// Reads 8 bits and returns them as a `u8`.
155    ///
156    /// Returns `None` when fewer than 8 bits remain.
157    #[allow(dead_code)]
158    pub fn read_byte(&mut self) -> Option<u8> {
159        self.read_bits(8).map(|v| v as u8)
160    }
161
162    /// Returns the number of bits remaining (bits not yet read).
163    #[allow(dead_code)]
164    pub fn bits_remaining(&self) -> usize {
165        let total_bits = self.data.len() * 8;
166        let consumed = self.byte_pos * 8 + usize::from(self.bit_pos);
167        total_bits.saturating_sub(consumed)
168    }
169
170    /// Returns `true` when all bits have been consumed.
171    #[allow(dead_code)]
172    pub fn is_exhausted(&self) -> bool {
173        self.bits_remaining() == 0
174    }
175}
176
177#[cfg(test)]
178mod tests {
179    use super::*;
180
181    // --- BitstreamWriter tests ---
182
183    #[test]
184    fn writer_new_is_empty() {
185        let w = BitstreamWriter::new();
186        assert_eq!(w.bits_written(), 0);
187        assert_eq!(w.bytes_used(), 0);
188    }
189
190    #[test]
191    fn writer_flush_empty() {
192        let w = BitstreamWriter::new();
193        assert!(w.flush().is_empty());
194    }
195
196    #[test]
197    fn writer_write_single_bit_one() {
198        let mut w = BitstreamWriter::new();
199        w.write_bit(true);
200        assert_eq!(w.bits_written(), 1);
201        let buf = w.flush();
202        assert_eq!(buf, vec![0x80]); // 1000_0000
203    }
204
205    #[test]
206    fn writer_write_single_bit_zero() {
207        let mut w = BitstreamWriter::new();
208        w.write_bit(false);
209        assert_eq!(w.bits_written(), 1);
210        let buf = w.flush();
211        assert_eq!(buf, vec![0x00]);
212    }
213
214    #[test]
215    fn writer_write_byte_roundtrip() {
216        for byte in [0x00u8, 0xFF, 0xAA, 0x55, 0x12, 0xAB] {
217            let mut w = BitstreamWriter::new();
218            w.write_byte(byte);
219            let buf = w.flush();
220            assert_eq!(buf, vec![byte], "failed for byte 0x{byte:02X}");
221        }
222    }
223
224    #[test]
225    fn writer_write_bits_4() {
226        // Write 0b1011 as 4 bits, then flush → 0b1011_0000 = 0xB0
227        let mut w = BitstreamWriter::new();
228        w.write_bits(0b1011, 4);
229        assert_eq!(w.bits_written(), 4);
230        let buf = w.flush();
231        assert_eq!(buf, vec![0xB0]);
232    }
233
234    #[test]
235    fn writer_bits_written_and_bytes_used() {
236        let mut w = BitstreamWriter::new();
237        w.write_bits(0xFF, 8);
238        assert_eq!(w.bytes_used(), 1);
239        assert_eq!(w.bits_written(), 8);
240        w.write_bit(true);
241        // 9 bits: 1 complete byte + 1 bit pending
242        assert_eq!(w.bytes_used(), 1);
243        assert_eq!(w.bits_written(), 9);
244    }
245
246    #[test]
247    fn writer_multiple_bytes() {
248        let mut w = BitstreamWriter::new();
249        w.write_byte(0xDE);
250        w.write_byte(0xAD);
251        let buf = w.flush();
252        assert_eq!(buf, vec![0xDE, 0xAD]);
253    }
254
255    // --- BitstreamReader tests ---
256
257    #[test]
258    fn reader_empty_is_exhausted() {
259        let r = BitstreamReader::new(vec![]);
260        assert!(r.is_exhausted());
261        assert_eq!(r.bits_remaining(), 0);
262    }
263
264    #[test]
265    fn reader_read_bit_from_single_byte() {
266        // 0xA5 = 1010_0101
267        let mut r = BitstreamReader::new(vec![0xA5]);
268        assert_eq!(r.read_bit(), Some(true));
269        assert_eq!(r.read_bit(), Some(false));
270        assert_eq!(r.read_bit(), Some(true));
271        assert_eq!(r.read_bit(), Some(false));
272        assert_eq!(r.read_bit(), Some(false));
273        assert_eq!(r.read_bit(), Some(true));
274        assert_eq!(r.read_bit(), Some(false));
275        assert_eq!(r.read_bit(), Some(true));
276        assert_eq!(r.read_bit(), None); // exhausted
277    }
278
279    #[test]
280    fn reader_bits_remaining_decrements() {
281        let mut r = BitstreamReader::new(vec![0xFF]);
282        assert_eq!(r.bits_remaining(), 8);
283        r.read_bit();
284        assert_eq!(r.bits_remaining(), 7);
285    }
286
287    #[test]
288    fn reader_read_byte_full() {
289        let mut r = BitstreamReader::new(vec![0x42]);
290        assert_eq!(r.read_byte(), Some(0x42));
291        assert!(r.is_exhausted());
292    }
293
294    #[test]
295    fn reader_read_byte_insufficient() {
296        let mut r = BitstreamReader::new(vec![]);
297        assert_eq!(r.read_byte(), None);
298    }
299
300    // --- Round-trip tests ---
301
302    #[test]
303    fn roundtrip_byte_sequence() {
304        let original = vec![0xDE_u8, 0xAD, 0xBE, 0xEF];
305        let mut w = BitstreamWriter::new();
306        for &b in &original {
307            w.write_byte(b);
308        }
309        let buf = w.flush();
310        let mut r = BitstreamReader::new(buf);
311        for &expected in &original {
312            assert_eq!(r.read_byte(), Some(expected));
313        }
314        assert!(r.is_exhausted());
315    }
316
317    #[test]
318    fn roundtrip_mixed_bit_widths() {
319        // Write: 3-bit field (0b101=5), 5-bit field (0b10110=22), 8-bit byte (0xFF).
320        let mut w = BitstreamWriter::new();
321        w.write_bits(5, 3);
322        w.write_bits(22, 5);
323        w.write_byte(0xFF);
324        let buf = w.flush();
325
326        let mut r = BitstreamReader::new(buf);
327        assert_eq!(r.read_bits(3), Some(5));
328        assert_eq!(r.read_bits(5), Some(22));
329        assert_eq!(r.read_byte(), Some(0xFF));
330        assert!(r.is_exhausted());
331    }
332
333    #[test]
334    fn roundtrip_single_bits() {
335        let bits = [true, false, true, true, false, false, true, false];
336        let mut w = BitstreamWriter::new();
337        for &b in &bits {
338            w.write_bit(b);
339        }
340        let buf = w.flush();
341
342        let mut r = BitstreamReader::new(buf);
343        for &expected in &bits {
344            assert_eq!(r.read_bit(), Some(expected));
345        }
346        assert!(r.is_exhausted());
347    }
348
349    #[test]
350    fn roundtrip_64bit_value() {
351        let value: u64 = 0xDEAD_BEEF_CAFE_1234;
352        let mut w = BitstreamWriter::new();
353        w.write_bits(value, 64);
354        let buf = w.flush();
355        assert_eq!(buf.len(), 8);
356        let mut r = BitstreamReader::new(buf);
357        let read_back = r.read_bits(64).expect("should succeed");
358        assert_eq!(read_back, value);
359        assert!(r.is_exhausted());
360    }
361}