protobuf_to_json/
varint.rs

1//! Variable-length integer decoding.
2//!
3
4/// Most-significant byte, == 0x80
5pub const MSB: u8 = 0b1000_0000;
6/// All bits except for the most significant. Can be used as bitmask to drop the most-signficant
7/// bit using `&` (binary-and).
8const DROP_MSB: u8 = 0b0111_1111;
9
10/// Decode a variable-length integer from a byte slice.
11pub fn decode_var(src: &mut &[u8]) -> Result<u64, ()> {
12    let mut result: u64 = 0;
13    let mut shift = 0;
14
15    let mut success = false;
16    for b in src.iter() {
17        let msb_dropped = b & DROP_MSB;
18        result |= (msb_dropped as u64) << shift;
19        shift += 7;
20
21        if b & MSB == 0 || shift > (9 * 7) {
22            success = b & MSB == 0;
23            break;
24        }
25    }
26
27    if success {
28        *src = &src[shift / 7..];
29        Ok(result)
30    } else {
31        Err(())
32    }
33}
34
35#[cfg(test)]
36mod tests {
37    use super::*;
38
39    #[test]
40    fn test_decode_max_u64() {
41        let max_vec_encoded = vec![0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01];
42        assert_eq!(
43            decode_var(&mut max_vec_encoded.as_slice()).unwrap(),
44            u64::max_value()
45        );
46    }
47
48    #[test]
49    fn test_decode_zero() {
50        let zero_encoded = vec![0x00];
51        assert_eq!(decode_var(&mut zero_encoded.as_slice()).unwrap(), 0);
52    }
53
54    #[test]
55    fn test_decode_one() {
56        let one_encoded = vec![0x01];
57        assert_eq!(decode_var(&mut one_encoded.as_slice()).unwrap(), 1);
58    }
59
60    #[test]
61    fn test_decode_large_number() {
62        let large_number_encoded = vec![0xAC, 0x02];
63        assert_eq!(
64            decode_var(&mut large_number_encoded.as_slice()).unwrap(),
65            300
66        );
67    }
68
69    #[test]
70    fn test_decode_incomplete_sequence() {
71        let incomplete_encoded = vec![0xFF, 0xFF, 0xFF];
72        assert!(decode_var(&mut incomplete_encoded.as_slice()).is_err());
73    }
74
75    #[test]
76    fn test_decode_single_byte_with_msb() {
77        let single_byte_with_msb = vec![0x80];
78        assert!(decode_var(&mut single_byte_with_msb.as_slice()).is_err());
79    }
80
81    #[test]
82    fn test_decode_empty_input() {
83        let empty_input: Vec<u8> = vec![];
84        assert!(decode_var(&mut empty_input.as_slice()).is_err());
85    }
86}