gamut_bitstream/
leb128.rs1pub fn write_leb128(out: &mut Vec<u8>, mut value: u64) {
8 loop {
9 let mut byte = (value & 0x7f) as u8;
10 value >>= 7;
11 if value != 0 {
12 byte |= 0x80;
13 }
14 out.push(byte);
15 if value == 0 {
16 break;
17 }
18 }
19}
20
21#[must_use]
23pub fn leb128_len(mut value: u64) -> usize {
24 let mut n = 1;
25 while value >= 0x80 {
26 value >>= 7;
27 n += 1;
28 }
29 n
30}
31
32#[cfg(test)]
33mod tests {
34 use super::*;
35
36 fn read_leb128(bytes: &[u8]) -> (u64, usize) {
38 let mut value = 0u64;
39 let mut i = 0;
40 loop {
41 let byte = bytes[i];
42 value |= u64::from(byte & 0x7f) << (7 * i);
43 i += 1;
44 if byte & 0x80 == 0 {
45 break;
46 }
47 }
48 (value, i)
49 }
50
51 #[test]
52 fn known_encodings() {
53 let mut out = Vec::new();
54 write_leb128(&mut out, 0);
55 assert_eq!(out, &[0x00]);
56
57 out.clear();
58 write_leb128(&mut out, 127);
59 assert_eq!(out, &[0x7f]);
60
61 out.clear();
62 write_leb128(&mut out, 128);
63 assert_eq!(out, &[0x80, 0x01]);
64
65 out.clear();
66 write_leb128(&mut out, 0x3fff);
67 assert_eq!(out, &[0xff, 0x7f]);
68 }
69
70 #[test]
71 fn len_matches_written_and_roundtrips() {
72 for &v in &[0u64, 1, 127, 128, 300, 0xffff, 0x10_0000, u32::MAX as u64] {
73 let mut out = Vec::new();
74 write_leb128(&mut out, v);
75 assert_eq!(out.len(), leb128_len(v), "len mismatch for {v}");
76 let (decoded, used) = read_leb128(&out);
77 assert_eq!(decoded, v);
78 assert_eq!(used, out.len());
79 }
80 }
81}