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}