1use crate::error::{Error, Result};
8
9#[inline]
11pub fn encode(mut value: u64, buf: &mut Vec<u8>) {
12 while value >= 0x80 {
13 buf.push(u8::try_from(value & 0xFF).unwrap_or(0) | 0x80);
14 value >>= 7;
15 }
16 buf.push(u8::try_from(value & 0xFF).unwrap_or(0));
17}
18
19#[inline]
26pub fn decode(data: &[u8], pos: &mut usize) -> Result<u64> {
27 let mut result: u64 = 0;
28 let mut shift: u32 = 0;
29 loop {
30 if *pos >= data.len() {
31 return Err(Error::TruncatedVarint(*pos));
32 }
33 if shift >= 70 {
34 return Err(Error::OverflowVarint);
35 }
36 let byte = *data.get(*pos).ok_or(Error::TruncatedVarint(*pos))?;
37 *pos += 1;
38 result |= u64::from(byte & 0x7F) << shift;
39 if byte & 0x80 == 0 {
40 return Ok(result);
41 }
42 shift += 7;
43 }
44}
45
46#[inline]
48#[must_use]
49pub fn encoded_len(value: u64) -> usize {
50 if value == 0 {
51 return 1;
52 }
53 let bits = usize::try_from(64 - value.leading_zeros()).unwrap_or(0);
54 bits.div_ceil(7)
55}
56
57#[cfg(test)]
58#[allow(clippy::as_conversions, clippy::unwrap_used, clippy::indexing_slicing)]
59mod tests {
60 use super::*;
61
62 #[test]
63 fn roundtrip_small() {
64 for v in 0..300u64 {
65 let mut buf = Vec::new();
66 encode(v, &mut buf);
67 let mut pos = 0;
68 assert_eq!(decode(&buf, &mut pos).unwrap(), v);
69 assert_eq!(pos, buf.len());
70 }
71 }
72
73 #[test]
74 fn roundtrip_large() {
75 let values = [0, 1, 127, 128, 16383, 16384, u64::from(u32::MAX), u64::MAX];
76 for &v in &values {
77 let mut buf = Vec::new();
78 encode(v, &mut buf);
79 let mut pos = 0;
80 assert_eq!(decode(&buf, &mut pos).unwrap(), v);
81 }
82 }
83
84 #[test]
85 fn encoded_lengths() {
86 assert_eq!(encoded_len(0), 1);
87 assert_eq!(encoded_len(127), 1);
88 assert_eq!(encoded_len(128), 2);
89 assert_eq!(encoded_len(16383), 2);
90 assert_eq!(encoded_len(16384), 3);
91 }
92
93 #[test]
94 fn truncated_error() {
95 let mut pos = 0;
96 assert!(decode(&[0x80], &mut pos).is_err());
97 }
98
99 #[test]
100 fn multiple_sequential() {
101 let mut buf = Vec::new();
102 encode(42, &mut buf);
103 encode(1000, &mut buf);
104 encode(0, &mut buf);
105
106 let mut pos = 0;
107 assert_eq!(decode(&buf, &mut pos).unwrap(), 42);
108 assert_eq!(decode(&buf, &mut pos).unwrap(), 1000);
109 assert_eq!(decode(&buf, &mut pos).unwrap(), 0);
110 assert_eq!(pos, buf.len());
111 }
112}