Skip to main content

read_fonts/collections/int_set/
output_bit_stream.rs

1//! Writes individual bits to a vector of bytes.
2
3use super::sparse_bit_set::BranchFactor;
4use alloc::vec::Vec;
5
6pub(crate) struct OutputBitStream {
7    data: Vec<u8>,
8    sub_index: u32,
9    branch_factor: BranchFactor,
10}
11
12impl OutputBitStream {
13    pub(crate) const MAX_HEIGHT: u8 = 31;
14
15    pub(crate) fn new(branch_factor: BranchFactor, height: u8) -> OutputBitStream {
16        let mut out = OutputBitStream {
17            data: Vec::new(),
18            sub_index: 0,
19            branch_factor,
20        };
21        if height > Self::MAX_HEIGHT {
22            panic!("Height value exceeds maximum for the branch factor.");
23        }
24        out.write_header(height);
25        out
26    }
27
28    pub fn into_bytes(self) -> Vec<u8> {
29        self.data
30    }
31
32    /// Writes a single node worth of bits to the stream.
33    ///
34    /// `branch_factor` controls the node size.
35    pub fn write_node(&mut self, bits: u32) {
36        for byte_index in 0..self.branch_factor.bytes_per_node() {
37            if self.branch_factor.nodes_per_byte() == 1 || self.sub_index == 0 {
38                self.data.push(0);
39            }
40
41            let bits = (bits >> (byte_index * 8)) & self.branch_factor.byte_mask();
42            let bits = (bits << (self.sub_index * self.branch_factor.value())) as u8;
43            *self.data.last_mut().unwrap() |= bits;
44
45            if self.branch_factor.nodes_per_byte() > 1 {
46                self.sub_index = (self.sub_index + 1) % self.branch_factor.nodes_per_byte();
47            }
48        }
49    }
50
51    /// Writes the header byte for a sparse bit set.
52    ///
53    /// See: <https://w3c.github.io/IFT/Overview.html#sparse-bit-set-decoding>
54    fn write_header(&mut self, height: u8) {
55        let byte = (height & 0b00011111) << 2;
56        let byte = byte | self.branch_factor.bit_id();
57        self.data.push(byte);
58    }
59}
60
61impl BranchFactor {
62    fn nodes_per_byte(&self) -> u32 {
63        match self {
64            BranchFactor::Two => 4,
65            BranchFactor::Four => 2,
66            BranchFactor::Eight => 1,
67            BranchFactor::ThirtyTwo => 1,
68        }
69    }
70
71    fn bytes_per_node(&self) -> u32 {
72        match self {
73            BranchFactor::Two => 1,
74            BranchFactor::Four => 1,
75            BranchFactor::Eight => 1,
76            BranchFactor::ThirtyTwo => 4,
77        }
78    }
79
80    fn bit_id(&self) -> u8 {
81        match self {
82            BranchFactor::Two => 0b00,
83            BranchFactor::Four => 0b01,
84            BranchFactor::Eight => 0b10,
85            BranchFactor::ThirtyTwo => 0b11,
86        }
87    }
88}
89
90#[cfg(test)]
91#[allow(clippy::unusual_byte_groupings)]
92mod test {
93    use super::*;
94
95    #[test]
96    fn init() {
97        let os = OutputBitStream::new(BranchFactor::Two, 13);
98        assert_eq!(os.into_bytes(), vec![0b0_01101_00]);
99
100        let os = OutputBitStream::new(BranchFactor::Four, 23);
101        assert_eq!(os.into_bytes(), vec![0b0_10111_01]);
102
103        let os = OutputBitStream::new(BranchFactor::Eight, 1);
104        assert_eq!(os.into_bytes(), vec![0b0_00001_10]);
105
106        let os = OutputBitStream::new(BranchFactor::ThirtyTwo, 31);
107        assert_eq!(os.into_bytes(), vec![0b0_11111_11]);
108    }
109
110    #[test]
111    fn bf2() {
112        let mut os = OutputBitStream::new(BranchFactor::Two, 13);
113
114        os.write_node(0b10);
115        os.write_node(0b00);
116        os.write_node(0b11);
117        os.write_node(0b01);
118
119        os.write_node(0b01);
120        os.write_node(0b11);
121
122        assert_eq!(
123            os.into_bytes(),
124            vec![0b0_01101_00, 0b01_11_00_10, 0b00_00_11_01,]
125        );
126    }
127
128    #[test]
129    fn bf4() {
130        let mut os = OutputBitStream::new(BranchFactor::Four, 23);
131
132        os.write_node(0b0010);
133        os.write_node(0b0111);
134
135        os.write_node(0b1101);
136
137        assert_eq!(
138            os.into_bytes(),
139            vec![0b0_10111_01, 0b0111_0010, 0b0000_1101,]
140        );
141    }
142
143    #[test]
144    fn bf8() {
145        let mut os = OutputBitStream::new(BranchFactor::Eight, 1);
146
147        os.write_node(0b01110010);
148        os.write_node(0b00001101);
149
150        assert_eq!(os.into_bytes(), vec![0b0_00001_10, 0b01110010, 0b00001101,]);
151    }
152
153    #[test]
154    fn bf32() {
155        let mut os = OutputBitStream::new(BranchFactor::ThirtyTwo, 31);
156
157        os.write_node(0b10000000_00000000_00001101_01110010);
158
159        assert_eq!(
160            os.into_bytes(),
161            vec![0b0_11111_11, 0b01110010, 0b00001101, 0b00000000, 0b10000000]
162        );
163    }
164
165    #[test]
166    fn truncating() {
167        let mut os = OutputBitStream::new(BranchFactor::Four, 23);
168
169        os.write_node(0b11110010);
170
171        assert_eq!(os.into_bytes(), vec![0b0_10111_01, 0b0000_0010]);
172    }
173}