blackbox_log/parser/decode/
variable.rs

1use super::zig_zag_decode;
2use crate::parser::{InternalError, InternalResult};
3use crate::Reader;
4
5pub(crate) fn variable(data: &mut Reader) -> InternalResult<u32> {
6    let mut uvar: u32 = 0;
7    let mut offset: u32 = 0;
8    loop {
9        let byte = data.read_u8().ok_or(InternalError::Eof)?;
10        let is_last_byte = (byte & 0x80) == 0;
11
12        let byte = u32::from(byte & !0x80);
13        uvar |= byte << offset;
14        offset += 7;
15
16        if !is_last_byte && offset >= 32 {
17            return Err(InternalError::Retry);
18        }
19
20        if is_last_byte {
21            break;
22        }
23    }
24
25    Ok(uvar)
26}
27
28pub(crate) fn variable_signed(data: &mut Reader) -> InternalResult<i32> {
29    variable(data).map(zig_zag_decode)
30}
31
32#[cfg(test)]
33mod tests {
34    use super::*;
35
36    fn read_ok(bytes: &[u8]) -> u32 {
37        variable(&mut Reader::new(bytes)).unwrap()
38    }
39
40    #[test]
41    fn zero() {
42        assert_eq!(0, read_ok(&[0x00]));
43        assert_eq!(0, read_ok(&[0x80, 0x00]));
44    }
45
46    #[test]
47    fn one() {
48        assert_eq!(1, read_ok(&[1]));
49    }
50
51    #[test]
52    fn full_byte_output() {
53        assert_eq!(0xFF, read_ok(&[0xFF, 0x01]));
54    }
55
56    #[test]
57    fn max_two_byte_input() {
58        assert_eq!(0x3FFF, read_ok(&[0xFF, 0x7F]));
59    }
60
61    #[test]
62    fn max() {
63        assert_eq!(0xFFFF_FFFF, read_ok(&[0xFF, 0xFF, 0xFF, 0xFF, 0x7F]));
64    }
65
66    #[test]
67    #[should_panic(expected = "Retry")]
68    fn too_many_bytes() {
69        assert_eq!(0xFFFF_FFFF, read_ok(&[0x80, 0x80, 0x80, 0x80, 0x80]));
70    }
71}