1use crate::check::Check;
9use crate::error::{Error, Result};
10use crate::io::{Reader, Writer};
11
12pub const MAX_LEN: usize = 10;
14
15pub fn decode(reader: &mut Reader<'_>) -> Result<u64> {
19 let start = reader.pos();
20 let mut result: u64 = 0;
21 let mut shift: u32 = 0;
22 let mut count = 0usize;
23 loop {
24 if count == MAX_LEN {
25 return Err(Error::new(
26 Check::ReeVarint,
27 format!("varint at offset {start} is longer than {MAX_LEN} bytes"),
28 ));
29 }
30 let byte = match reader.u8() {
31 Ok(b) => b,
32 Err(_) => {
33 return Err(Error::new(
34 Check::ReeVarint,
35 format!("varint at offset {start} runs past the end of its buffer"),
36 ))
37 }
38 };
39 count += 1;
40 if count == MAX_LEN && byte > 0x01 {
41 return Err(Error::new(
42 Check::ReeVarint,
43 format!("varint at offset {start} overflows 64 bits"),
44 ));
45 }
46 result |= u64::from(byte & 0x7F) << shift;
47 if byte & 0x80 == 0 {
48 if count > 1 && byte == 0 {
49 return Err(Error::new(
50 Check::ReeVarint,
51 format!("varint at offset {start} is not minimally encoded"),
52 ));
53 }
54 return Ok(result);
55 }
56 shift += 7;
57 }
58}
59
60pub fn encode(out: &mut Writer, value: u64) {
62 let mut v = value;
63 while v >= 0x80 {
64 out.u8((v as u8) | 0x80);
65 v >>= 7;
66 }
67 out.u8(v as u8);
68}
69
70pub fn encoded_len(value: u64) -> usize {
72 let mut len = 1;
73 let mut v = value >> 7;
74 while v != 0 {
75 len += 1;
76 v >>= 7;
77 }
78 len
79}
80
81pub fn to_vec(value: u64) -> Vec<u8> {
83 let mut w = Writer::with_capacity(encoded_len(value));
84 encode(&mut w, value);
85 w.into_vec()
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 fn round_trip(value: u64) {
93 let bytes = to_vec(value);
94 assert_eq!(bytes.len(), encoded_len(value));
95 let mut r = Reader::new(&bytes);
96 assert_eq!(r.varint().unwrap(), value);
97 assert!(r.is_empty());
98 }
99
100 #[test]
101 fn spec_examples() {
102 assert_eq!(to_vec(0), vec![0x00]);
103 assert_eq!(to_vec(128), vec![0x80, 0x01]);
104 assert_eq!(to_vec(2_073_600).len(), 3); assert_eq!(to_vec(74_649_600).len(), 4); }
107
108 #[test]
109 fn round_trips_boundaries() {
110 for value in [
111 0,
112 1,
113 127,
114 128,
115 16_383,
116 16_384,
117 2_097_151,
118 2_097_152,
119 268_435_455,
120 268_435_456,
121 u64::MAX,
122 ] {
123 round_trip(value);
124 }
125 }
126
127 #[test]
128 fn overlong_is_rejected() {
129 let mut r = Reader::new(&[0x80, 0x00]);
130 let err = r.varint().unwrap_err();
131 assert_eq!(err.check(), Check::ReeVarint);
132 }
133
134 #[test]
135 fn truncated_is_rejected() {
136 let mut r = Reader::new(&[0x80]);
137 assert_eq!(r.varint().unwrap_err().check(), Check::ReeVarint);
138 }
139
140 #[test]
141 fn overflow_is_rejected() {
142 let mut bytes = vec![0xFFu8; 10];
144 bytes.push(0x01);
145 let mut r = Reader::new(&bytes);
146 assert_eq!(r.varint().unwrap_err().check(), Check::ReeVarint);
147 }
148
149 #[test]
150 fn max_u64_round_trips_in_ten_bytes() {
151 let bytes = to_vec(u64::MAX);
152 assert_eq!(bytes.len(), 10);
153 let mut r = Reader::new(&bytes);
154 assert_eq!(r.varint().unwrap(), u64::MAX);
155 }
156}