Skip to main content

vexil_runtime/
leb128.rs

1use crate::error::DecodeError;
2
3/// Encode `value` as an unsigned LEB128 varint, appending bytes to `buf`.
4pub fn encode(buf: &mut Vec<u8>, mut value: u64) {
5    loop {
6        let mut byte = (value & 0x7F) as u8;
7        value >>= 7;
8        if value != 0 {
9            byte |= 0x80;
10        }
11        buf.push(byte);
12        if value == 0 {
13            break;
14        }
15    }
16}
17
18/// Decode an unsigned LEB128 varint from `data`, consuming at most `max_bytes`.
19///
20/// Returns `(value, bytes_consumed)` on success. Returns
21/// [`DecodeError::InvalidVarint`] for overlong encodings or if the varint
22/// exceeds `max_bytes`, and [`DecodeError::UnexpectedEof`] if the input ends
23/// before a terminating byte.
24pub fn decode(data: &[u8], max_bytes: u8) -> Result<(u64, usize), DecodeError> {
25    let mut result: u64 = 0;
26    let mut shift: u32 = 0;
27
28    for (i, &byte) in data.iter().enumerate() {
29        if i >= max_bytes as usize {
30            return Err(DecodeError::InvalidVarint);
31        }
32        result |= u64::from(byte & 0x7F) << shift;
33        shift += 7;
34
35        if byte & 0x80 == 0 {
36            // Reject overlong: if not first byte and byte is 0
37            if i > 0 && byte == 0 {
38                return Err(DecodeError::InvalidVarint);
39            }
40            return Ok((result, i + 1));
41        }
42    }
43    Err(DecodeError::UnexpectedEof)
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn encode_zero() {
52        let mut b = Vec::new();
53        encode(&mut b, 0);
54        assert_eq!(b, [0x00]);
55    }
56
57    #[test]
58    fn encode_127() {
59        let mut b = Vec::new();
60        encode(&mut b, 127);
61        assert_eq!(b, [0x7F]);
62    }
63
64    #[test]
65    fn encode_128() {
66        let mut b = Vec::new();
67        encode(&mut b, 128);
68        assert_eq!(b, [0x80, 0x01]);
69    }
70
71    #[test]
72    fn encode_300() {
73        let mut b = Vec::new();
74        encode(&mut b, 300);
75        assert_eq!(b, [0xAC, 0x02]);
76    }
77
78    #[test]
79    fn round_trip_max_u64() {
80        let mut buf = Vec::new();
81        encode(&mut buf, u64::MAX);
82        let (val, consumed) = decode(&buf, 10).unwrap();
83        assert_eq!(val, u64::MAX);
84        assert_eq!(consumed, 10);
85    }
86
87    #[test]
88    fn decode_max_4_bytes_limit() {
89        let mut buf = Vec::new();
90        encode(&mut buf, (1 << 28) - 1);
91        assert!(buf.len() <= 4);
92        let (val, _) = decode(&buf, 4).unwrap();
93        assert_eq!(val, (1 << 28) - 1);
94    }
95
96    #[test]
97    fn decode_exceeds_max_bytes() {
98        let mut buf = Vec::new();
99        encode(&mut buf, 1 << 28);
100        assert!(decode(&buf, 4).is_err());
101    }
102
103    #[test]
104    fn reject_overlong_encoding() {
105        let buf = [0x80, 0x00];
106        assert!(decode(&buf, 10).is_err());
107    }
108}