1const MAX_VARINT_BYTES: usize = 10;
4
5pub fn encode_varint(mut value: u64, buf: &mut [u8]) -> usize {
28 let mut i = 0;
29 loop {
30 let mut byte = (value & 0x7F) as u8;
32 value >>= 7;
33
34 if value > 0 {
35 byte |= 0x80;
37 }
38
39 buf[i] = byte;
40 i += 1;
41
42 if value == 0 {
43 break;
44 }
45 }
46 i
47}
48
49use crate::error::WireError;
50
51pub fn decode_varint(buf: &[u8]) -> Result<(u64, usize), WireError> {
63 let mut result: u64 = 0;
64 let mut shift: u32 = 0;
65
66 for (i, &byte) in buf.iter().enumerate() {
67 if i >= MAX_VARINT_BYTES {
68 return Err(WireError::VarintTooLong);
69 }
70
71 let data = u64::from(byte & 0x7F);
73 result |= data << shift;
74 shift += 7;
75
76 if byte & 0x80 == 0 {
78 return Ok((result, i + 1));
79 }
80 }
81
82 Err(WireError::UnexpectedEof { offset: buf.len() })
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 fn encode(value: u64) -> Vec<u8> {
92 let mut buf = [0u8; MAX_VARINT_BYTES];
93 let len = encode_varint(value, &mut buf);
94 buf[..len].to_vec()
95 }
96
97 #[test]
98 fn encode_zero() {
99 assert_eq!(encode(0), vec![0x00]);
100 }
101
102 #[test]
103 fn encode_one() {
104 assert_eq!(encode(1), vec![0x01]);
105 }
106
107 #[test]
108 fn encode_127() {
109 assert_eq!(encode(127), vec![0x7F]);
111 }
112
113 #[test]
114 fn encode_128() {
115 assert_eq!(encode(128), vec![0x80, 0x01]);
117 }
118
119 #[test]
120 fn encode_300() {
121 assert_eq!(encode(300), vec![0xAC, 0x02]);
123 }
124
125 #[test]
126 fn encode_16383() {
127 assert_eq!(encode(16383), vec![0xFF, 0x7F]);
129 }
130
131 #[test]
132 fn encode_16384() {
133 assert_eq!(encode(16384), vec![0x80, 0x80, 0x01]);
135 }
136
137 #[test]
138 fn encode_u32_max() {
139 let bytes = encode(u64::from(u32::MAX));
140 assert_eq!(bytes.len(), 5);
141 }
142
143 #[test]
144 fn encode_u64_max() {
145 let bytes = encode(u64::MAX);
146 assert_eq!(bytes.len(), MAX_VARINT_BYTES);
147 }
148
149 #[test]
150 fn roundtrip_boundary_values() {
151 let values = [
152 0,
153 1,
154 127,
155 128,
156 255,
157 256,
158 16383,
159 16384,
160 u64::from(u32::MAX),
161 u64::MAX,
162 ];
163 for &value in &values {
164 let encoded = encode(value);
165 let (decoded, consumed) = decode_varint(&encoded).unwrap();
166 assert_eq!(decoded, value, "roundtrip failed for {value}");
167 assert_eq!(consumed, encoded.len());
168 }
169 }
170
171 #[test]
172 fn decode_with_trailing_bytes() {
173 let buf = [0xAC, 0x02, 0xFF, 0xFF];
175 let (value, consumed) = decode_varint(&buf).unwrap();
176 assert_eq!(value, 300);
177 assert_eq!(consumed, 2);
178 }
179
180 #[test]
181 fn decode_empty_input() {
182 let result = decode_varint(&[]);
183 assert!(matches!(
184 result,
185 Err(WireError::UnexpectedEof { offset: 0 })
186 ));
187 }
188
189 #[test]
190 fn decode_truncated_varint() {
191 let result = decode_varint(&[0x80]);
193 assert!(matches!(result, Err(WireError::UnexpectedEof { .. })));
194 }
195
196 #[test]
197 fn decode_too_long() {
198 let buf = [0x80; 11];
200 let result = decode_varint(&buf);
201 assert!(matches!(result, Err(WireError::VarintTooLong)));
202 }
203}