blackbox_log/parser/decode/
variable.rs1use 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}