exp_golomb/decoder.rs
1/// An Exponential-Golomb parser.
2pub struct ExpGolombDecoder<'a> {
3 iter: BitIterator<'a>,
4}
5
6impl<'a> ExpGolombDecoder<'a> {
7 /// Create a new `ExpGolombDecoder`.
8 ///
9 /// `start` denotes the starting position in the first byte of `buf` and goes from 0 (first) to
10 /// 7 (last). This function returns `None` if the buffer is empty or if `start` is not within
11 /// \[0, 7\].
12 ///
13 /// # Examples
14 ///
15 /// ```
16 /// # use exp_golomb::ExpGolombDecoder;
17 /// let data = [0b01000000];
18 /// let mut reader = ExpGolombDecoder::new(&data, 0).unwrap();
19 /// assert_eq!(reader.next_unsigned(), Some(1));
20 /// ```
21 ///
22 /// Start at the second bit:
23 ///
24 /// ```
25 /// # use exp_golomb::ExpGolombDecoder;
26 /// // Same as above but `010` is shifted one place to the right
27 /// let data = [0b00100000];
28 /// let mut reader = ExpGolombDecoder::new(&data, 1).unwrap();
29 /// assert_eq!(reader.next_unsigned(), Some(1));
30 /// ```
31 #[inline]
32 #[must_use]
33 pub fn new(buf: &'a [u8], start: u32) -> Option<ExpGolombDecoder<'a>> {
34 if buf.is_empty() || start > 7 {
35 return None;
36 }
37 Some(ExpGolombDecoder {
38 iter: BitIterator::new(buf, start),
39 })
40 }
41
42 /// Read the next bit (i.e, as a flag). Returns `None` if the end of the bitstream is reached.
43 ///
44 /// # Examples
45 ///
46 /// ```
47 /// use exp_golomb::ExpGolombDecoder;
48 ///
49 /// let data = [0b01010101];
50 /// let mut reader = ExpGolombDecoder::new(&data, 4).unwrap();
51 ///
52 /// assert_eq!(reader.next_bit(), Some(0));
53 /// assert_eq!(reader.next_bit(), Some(1));
54 /// assert_eq!(reader.next_bit(), Some(0));
55 /// assert_eq!(reader.next_bit(), Some(1));
56 /// assert_eq!(reader.next_bit(), None);
57 /// assert_eq!(reader.next_bit(), None);
58 /// ```
59 #[inline]
60 pub fn next_bit(&mut self) -> Option<u8> {
61 self.iter.next()
62 }
63
64 #[inline]
65 fn count_leading_zeroes(&mut self) -> Option<u32> {
66 let mut leading_zeros = 0;
67 for bit in self.iter.by_ref() {
68 if bit == 0 {
69 leading_zeros += 1;
70 if leading_zeros > u64::BITS {
71 return None;
72 }
73 } else {
74 return Some(leading_zeros);
75 }
76 }
77 None
78 }
79
80 /// Read the next Exp-Golomb value as an unsigned integer. Returns `None` if the end of the
81 /// bitstream is reached before parsing is completed or if the coded value is exceeds the
82 /// limits of a `u64`.
83 ///
84 /// # Examples
85 ///
86 /// ```
87 /// # use exp_golomb::ExpGolombDecoder;
88 /// // 010 - 1
89 /// // 00110 - 5
90 /// // 00000000111111111 - 510
91 /// // 00101 - 4
92 /// // 01 - missing 1 more bit
93 /// let data = [0b01000110, 0b00000000, 0b11111111, 0b10010101];
94 ///
95 /// let mut reader = ExpGolombDecoder::new(&data, 0).unwrap();
96 /// assert_eq!(reader.next_unsigned(), Some(1));
97 /// assert_eq!(reader.next_unsigned(), Some(5));
98 /// assert_eq!(reader.next_unsigned(), Some(510));
99 /// assert_eq!(reader.next_unsigned(), Some(4));
100 /// assert_eq!(reader.next_unsigned(), None);
101 /// assert_eq!(reader.next_unsigned(), None);
102 /// ```
103 ///
104 /// The coded value is limited to 64 bits. Trying to parse larger values would return
105 /// `None`.
106 ///
107 /// ```
108 /// # use exp_golomb::ExpGolombDecoder;
109 /// let data = [
110 /// 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
111 /// 0b00000000, 0b00000001, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111,
112 /// 0b11111111, 0b11111111, 0b11111111,
113 /// ];
114 /// let mut reader = ExpGolombDecoder::new(&data, 7).unwrap();
115 /// assert_eq!(reader.next_unsigned(), Some(u64::MAX));
116 ///
117 /// // Attempt to parse a 65-bit number
118 /// let mut reader = ExpGolombDecoder::new(&data, 6).unwrap();
119 /// assert_eq!(reader.next_unsigned(), None);
120 /// ```
121 #[inline]
122 #[must_use = "use `ExpGolombReader::skip_next` if the value is not needed"]
123 pub fn next_unsigned(&mut self) -> Option<u64> {
124 let mut lz = self.count_leading_zeroes()?;
125 let x = 1u64.wrapping_shl(lz) - 1;
126 let mut y = 0;
127
128 if lz != 0 {
129 for bit in self.iter.by_ref() {
130 y <<= 1;
131 y |= bit as u64;
132 lz -= 1;
133 if lz == 0 {
134 break;
135 }
136 }
137 if lz != 0 {
138 return None;
139 }
140 }
141 Some(x + y)
142 }
143
144 /// Read the next Exp-Golomb value, interpreting it as a signed integer. Returns `None` if the
145 /// end of the bitstream is reached before parsing is completed or if the coded value is
146 /// exceeds the limits of a `i64`.
147 ///
148 /// # Examples
149 ///
150 /// ```
151 /// # use exp_golomb::ExpGolombDecoder;
152 /// // Concatenated Wikipedia example:
153 /// // https://en.wikipedia.org/wiki/Exponential-Golomb_coding#Extension_to_negative_numbers
154 /// let data = [0b10100110, 0b01000010, 0b10011000, 0b11100010, 0b00000100, 0b10000000];
155 ///
156 /// let mut reader = ExpGolombDecoder::new(&data, 0).unwrap();
157 /// assert_eq!(reader.next_signed(), Some(0));
158 /// assert_eq!(reader.next_signed(), Some(1));
159 /// assert_eq!(reader.next_signed(), Some(-1));
160 /// assert_eq!(reader.next_signed(), Some(2));
161 /// assert_eq!(reader.next_signed(), Some(-2));
162 /// assert_eq!(reader.next_signed(), Some(3));
163 /// assert_eq!(reader.next_signed(), Some(-3));
164 /// assert_eq!(reader.next_signed(), Some(4));
165 /// assert_eq!(reader.next_signed(), Some(-4));
166 /// assert_eq!(reader.next_signed(), None);
167 /// assert_eq!(reader.next_signed(), None);
168 /// ```
169 ///
170 /// The coded value is limited to 64 bits. Trying to parse larger values would return
171 /// `None`.
172 ///
173 /// ```
174 /// # use exp_golomb::ExpGolombDecoder;
175 /// let data = [
176 /// 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
177 /// 0b00000000, 0b00000001, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111,
178 /// 0b11111111, 0b11111111, 0b11111111,
179 /// ];
180 /// let mut reader = ExpGolombDecoder::new(&data, 7).unwrap();
181 /// assert_eq!(reader.next_signed(), Some(i64::MIN));
182 ///
183 /// // Attempt to parse a 65-bit number
184 /// let mut reader = ExpGolombDecoder::new(&data, 6).unwrap();
185 /// assert_eq!(reader.next_signed(), None);
186 /// ```
187 #[inline]
188 #[must_use = "use `ExpGolombReader::skip_next` if the value is not needed"]
189 pub fn next_signed(&mut self) -> Option<i64> {
190 self.next_unsigned().map(|k| {
191 let factor = if k % 2 == 0 { -1 } else { 1 };
192 factor * (k / 2 + k % 2) as i64
193 })
194 }
195
196 /// Skip the next Exp-Golomb encoded value. Any parsing error at the end of the bitstream is
197 /// ignored.
198 ///
199 /// # Examples
200 ///
201 /// ```
202 /// # use exp_golomb::ExpGolombDecoder;
203 /// let data = [0b01001001, 0b00110000];
204 /// let mut reader = ExpGolombDecoder::new(&data, 0).unwrap();
205 /// reader.skip_next();
206 /// reader.skip_next();
207 /// reader.skip_next();
208 /// assert_eq!(reader.next_unsigned(), Some(2));
209 /// reader.skip_next();
210 /// assert_eq!(reader.next_unsigned(), None);
211 /// reader.skip_next();
212 /// assert_eq!(reader.next_unsigned(), None);
213 /// ```
214 #[inline]
215 pub fn skip_next(&mut self) {
216 if let Some(lz) = self.count_leading_zeroes() {
217 self.iter.skip_bits(lz);
218 }
219 }
220}
221
222struct BitIterator<'a> {
223 buf: &'a [u8],
224 index: usize,
225 bit_pos: u32,
226}
227
228impl<'a> BitIterator<'a> {
229 #[inline]
230 fn new(buf: &'a [u8], shift_sub: u32) -> BitIterator<'a> {
231 Self {
232 buf,
233 index: 0,
234 bit_pos: shift_sub,
235 }
236 }
237
238 #[inline]
239 fn skip_bits(&mut self, num_bits: u32) {
240 let offset = self.bit_pos as usize + num_bits as usize;
241 self.index = usize::min(self.buf.len(), self.index + offset / 8);
242 self.bit_pos = (offset % 8) as u32;
243 }
244}
245
246impl<'a> core::iter::Iterator for BitIterator<'a> {
247 type Item = u8;
248
249 #[inline]
250 fn next(&mut self) -> Option<Self::Item> {
251 let curr_byte = *self.buf.get(self.index)?;
252 let shift = 7 - self.bit_pos;
253 let bit = curr_byte & (1 << shift);
254
255 self.bit_pos += 1;
256 if self.bit_pos == 8 {
257 self.bit_pos = 0;
258 // Increment only when the index has not reached the end of the buffer to prevent
259 // wrap-around to a valid index which will make this function return `Some` after
260 // signaling `None`
261 if self.index < self.buf.len() {
262 self.index += 1;
263 }
264 }
265
266 Some(bit >> shift)
267 }
268}
269
270#[cfg(test)]
271mod tests {
272 use super::*;
273
274 #[test]
275 fn empty_buffer() {
276 assert!(ExpGolombDecoder::new(&[], 0).is_none());
277 }
278
279 #[test]
280 fn start_bit_validity() {
281 let data = [0b01000000];
282 for i in 0..=7 {
283 assert!(ExpGolombDecoder::new(&data, i).is_some());
284 }
285 assert!(ExpGolombDecoder::new(&data, 8).is_none());
286 }
287
288 #[test]
289 fn shifted_data() {
290 let data: [(&[u8], u32, Option<u64>); 9] = [
291 (&[0b01000000], 0, Some(1)),
292 (&[0b00100000], 1, Some(1)),
293 (&[0b00010000], 2, Some(1)),
294 (&[0b00001000], 3, Some(1)),
295 (&[0b00000100], 4, Some(1)),
296 (&[0b00000010], 5, Some(1)),
297 (&[0b00000001], 6, None),
298 (&[0b00000001, 0], 6, Some(1)),
299 (&[0b00000000, 0b10000000], 7, Some(1)),
300 ];
301
302 for (buf, start, ans) in data {
303 let mut reader = ExpGolombDecoder::new(buf, start).unwrap();
304 let res = reader.next_unsigned();
305 assert_eq!(res, ans);
306 }
307 }
308
309 #[test]
310 fn mix_next_unsigned_with_next_bit() {
311 let data = [0b01010101];
312 let mut reader = ExpGolombDecoder::new(&data, 0).unwrap();
313 assert_eq!(reader.next_unsigned(), Some(1));
314 assert_eq!(reader.next_bit(), Some(1));
315 assert_eq!(reader.next_unsigned(), Some(1));
316 assert_eq!(reader.next_bit(), Some(1));
317 }
318}