1use std::fmt;
13
14pub const MAX: u64 = (1 << 62) - 1;
16
17pub const MAX_ENCODED_LEN: usize = 8;
19
20#[derive(Clone, Copy, Debug, PartialEq, Eq)]
22pub enum VarintError {
23 OutOfRange,
25 Truncated,
28}
29
30impl fmt::Display for VarintError {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 match self {
33 VarintError::OutOfRange => f.write_str("value exceeds the QUIC varint range"),
34 VarintError::Truncated => f.write_str("input ended inside a varint"),
35 }
36 }
37}
38
39impl std::error::Error for VarintError {}
40
41pub const fn varint_len(value: u64) -> usize {
43 if value < 1 << 6 {
44 1
45 } else if value < 1 << 14 {
46 2
47 } else if value < 1 << 30 {
48 4
49 } else {
50 8
51 }
52}
53
54pub fn write_varint(value: u64, out: &mut [u8]) -> Result<usize, VarintError> {
66 if value > MAX {
67 return Err(VarintError::OutOfRange);
68 }
69 let len = varint_len(value);
70 if out.len() < len {
71 return Err(VarintError::OutOfRange);
72 }
73 match len {
74 1 => out[0] = value as u8,
75 2 => out[..2].copy_from_slice(&((value as u16) | 0x4000).to_be_bytes()),
76 4 => out[..4].copy_from_slice(&((value as u32) | 0x8000_0000).to_be_bytes()),
77 _ => out[..8].copy_from_slice(&(value | 0xc000_0000_0000_0000).to_be_bytes()),
78 }
79 Ok(len)
80}
81
82pub fn encode_varint(value: u64, out: &mut Vec<u8>) -> Result<(), VarintError> {
88 let mut bytes = [0u8; 8];
89 let len = write_varint(value, &mut bytes)?;
90 out.extend_from_slice(&bytes[..len]);
91 Ok(())
92}
93
94pub fn decode_varint(input: &[u8]) -> Result<(u64, usize), VarintError> {
98 let first = *input.first().ok_or(VarintError::Truncated)?;
99 let len = 1usize << (first >> 6);
100 if input.len() < len {
101 return Err(VarintError::Truncated);
102 }
103 let mut value = u64::from(first & 0x3f);
104 for b in &input[1..len] {
105 value = (value << 8) | u64::from(*b);
106 }
107 Ok((value, len))
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 fn enc(v: u64) -> Vec<u8> {
115 let mut out = Vec::new();
116 encode_varint(v, &mut out).unwrap();
117 out
118 }
119
120 #[test]
121 fn rfc_9000_appendix_a_vectors() {
122 assert_eq!(
124 decode_varint(&[0xc2, 0x19, 0x7c, 0x5e, 0xff, 0x14, 0xe8, 0x8c]).unwrap(),
125 (151_288_809_941_952_652, 8)
126 );
127 assert_eq!(
128 decode_varint(&[0x9d, 0x7f, 0x3e, 0x7d]).unwrap(),
129 (494_878_333, 4)
130 );
131 assert_eq!(decode_varint(&[0x7b, 0xbd]).unwrap(), (15_293, 2));
132 assert_eq!(decode_varint(&[0x25]).unwrap(), (37, 1));
133 assert_eq!(decode_varint(&[0x40, 0x25]).unwrap(), (37, 2));
135 }
136
137 #[test]
138 fn encoding_is_minimal_at_every_boundary() {
139 let cases = [
140 (0u64, 1usize),
141 (63, 1),
142 (64, 2),
143 (16_383, 2),
144 (16_384, 4),
145 (1_073_741_823, 4),
146 (1_073_741_824, 8),
147 (MAX, 8),
148 ];
149 for (value, len) in cases {
150 assert_eq!(varint_len(value), len, "len of {value}");
151 assert_eq!(enc(value).len(), len, "encoded len of {value}");
152 assert_eq!(decode_varint(&enc(value)).unwrap(), (value, len));
153 }
154 }
155
156 #[test]
157 fn header_len_of_16384_is_the_four_byte_form() {
158 assert_eq!(enc(16_384), vec![0x80, 0x00, 0x40, 0x00]);
159 }
160
161 #[test]
162 fn out_of_range_is_rejected() {
163 let mut out = Vec::new();
164 assert_eq!(
165 encode_varint(MAX + 1, &mut out),
166 Err(VarintError::OutOfRange)
167 );
168 assert_eq!(
169 encode_varint(u64::MAX, &mut out),
170 Err(VarintError::OutOfRange)
171 );
172 assert!(out.is_empty(), "nothing is written on rejection");
173 }
174
175 #[test]
176 fn truncated_input_is_distinguishable_from_corruption() {
177 assert_eq!(decode_varint(&[]), Err(VarintError::Truncated));
178 assert_eq!(decode_varint(&[0x40]), Err(VarintError::Truncated));
179 assert_eq!(decode_varint(&[0x80, 0x00]), Err(VarintError::Truncated));
180 assert_eq!(decode_varint(&[0xc0; 7]), Err(VarintError::Truncated));
181 assert!(decode_varint(&[0xc0; 8]).is_ok());
182 }
183
184 #[test]
185 fn trailing_bytes_are_left_for_the_caller() {
186 let (v, n) = decode_varint(&[0x25, 0xff, 0xff]).unwrap();
187 assert_eq!((v, n), (37, 1));
188 }
189
190 #[test]
191 fn roundtrip_over_a_wide_spread_of_values() {
192 let mut x = 0x2545_f491_4f6c_dd1du64;
193 for _ in 0..2000 {
194 x ^= x << 13;
196 x ^= x >> 7;
197 x ^= x << 17;
198 let v = x & MAX;
199 assert_eq!(decode_varint(&enc(v)).unwrap().0, v);
200 }
201 }
202}