Skip to main content

bitstream/
lib.rs

1//! Low-level bit packing primitives for the sdec codec.
2//!
3//! This crate provides bounded [`BitWriter`] and [`BitReader`] for bit-level encoding and decoding.
4//! For convenience, [`BitVecWriter`] can be used when a growable buffer is acceptable.
5//! It is designed for bounded, panic-free operation with explicit error handling.
6//!
7//! # Design Principles
8//!
9//! - **No unsafe code** - Safety is paramount.
10//! - **Bounded operations** - All reads/writes are bounds-checked.
11//! - **No domain knowledge** - This crate knows nothing about entities, components, or game state.
12//! - **Explicit errors** - All failures return structured errors, never panic.
13//!
14//! # Example
15//!
16//! ```
17//! use bitstream::{BitReader, BitVecWriter};
18//!
19//! let mut writer = BitVecWriter::new();
20//! writer.write_bit(true);
21//! writer.write_bits(42, 7).unwrap();
22//!
23//! let bytes = writer.finish();
24//!
25//! let mut reader = BitReader::new(&bytes);
26//! assert!(reader.read_bit().unwrap());
27//! assert_eq!(reader.read_bits(7).unwrap(), 42);
28//! ```
29
30mod error;
31mod reader;
32mod writer;
33
34pub use error::{BitError, BitResult};
35pub use reader::BitReader;
36pub use writer::{BitVecWriter, BitWriter};
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41
42    #[test]
43    fn empty_roundtrip() {
44        let writer = BitVecWriter::new();
45        let bytes = writer.finish();
46        assert!(bytes.is_empty());
47
48        let reader = BitReader::new(&bytes);
49        assert!(reader.is_empty());
50    }
51
52    #[test]
53    fn single_bit_roundtrip() {
54        let mut writer = BitVecWriter::new();
55        writer.write_bit(true);
56        let bytes = writer.finish();
57
58        let mut reader = BitReader::new(&bytes);
59        assert!(reader.read_bit().unwrap());
60    }
61
62    #[test]
63    fn multiple_bits_roundtrip() {
64        let mut writer = BitVecWriter::new();
65        writer.write_bit(true);
66        writer.write_bit(false);
67        writer.write_bit(true);
68        writer.write_bit(true);
69        writer.write_bit(false);
70        let bytes = writer.finish();
71
72        let mut reader = BitReader::new(&bytes);
73        assert!(reader.read_bit().unwrap());
74        assert!(!reader.read_bit().unwrap());
75        assert!(reader.read_bit().unwrap());
76        assert!(reader.read_bit().unwrap());
77        assert!(!reader.read_bit().unwrap());
78    }
79
80    #[test]
81    fn bits_roundtrip_various_sizes() {
82        let test_cases = [
83            (0b1010u64, 4u8),
84            (0xFFu64, 8u8),
85            (0xABCDu64, 16u8),
86            (0x1234_5678u64, 32u8),
87            (u64::MAX, 64u8),
88        ];
89
90        for (value, bits) in test_cases {
91            let mut writer = BitVecWriter::new();
92            writer.write_bits(value, bits).unwrap();
93            let bytes = writer.finish();
94
95            let mut reader = BitReader::new(&bytes);
96            let read_value = reader.read_bits(bits).unwrap();
97            assert_eq!(
98                read_value, value,
99                "roundtrip failed for {bits}-bit value {value}"
100            );
101        }
102    }
103
104    #[test]
105    fn mixed_roundtrip() {
106        let mut writer = BitVecWriter::new();
107        writer.write_bit(true);
108        writer.write_bits(0b1010, 4).unwrap();
109        writer.write_bit(false);
110        writer.write_bits(0xFF, 8).unwrap();
111        writer.write_bits(42, 7).unwrap();
112        let bytes = writer.finish();
113
114        let mut reader = BitReader::new(&bytes);
115        assert!(reader.read_bit().unwrap());
116        assert_eq!(reader.read_bits(4).unwrap(), 0b1010);
117        assert!(!reader.read_bit().unwrap());
118        assert_eq!(reader.read_bits(8).unwrap(), 0xFF);
119        assert_eq!(reader.read_bits(7).unwrap(), 42);
120    }
121
122    #[test]
123    fn doctest_example() {
124        let mut writer = BitVecWriter::new();
125        writer.write_bit(true);
126        writer.write_bits(42, 7).unwrap();
127
128        let bytes = writer.finish();
129
130        let mut reader = BitReader::new(&bytes);
131        assert!(reader.read_bit().unwrap());
132        assert_eq!(reader.read_bits(7).unwrap(), 42);
133    }
134}