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