ddns/core/parser/
varint.rs1use std::{cmp::Ordering, convert::TryFrom, fmt};
2
3use bytes::BufMut;
4use nom::{
5 IResult,
6 error::{ErrorKind, make_error},
7 number::streaming::be_u8,
8};
9
10#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
19pub struct VarInt(u64);
20
21pub const VARINT_MAX: u64 = 0x3fff_ffff_ffff_ffff;
23
24#[allow(dead_code)]
29pub enum EncodeBytes {
30 One = 1,
31 Two = 2,
32 Four = 4,
33 Eight = 8,
34}
35
36impl VarInt {
37 pub const MAX: Self = Self(VARINT_MAX);
39 pub const MAX_SIZE: usize = 8;
41
42 pub const fn from_u32(x: u32) -> Self {
44 Self(x as u64)
45 }
46
47 pub const fn from_u64(value: u64) -> Result<Self, err::Overflow> {
50 if value <= VARINT_MAX {
51 Ok(Self(value))
52 } else {
53 Err(err::Overflow { value: value as _ })
54 }
55 }
56
57 pub unsafe fn from_u64_unchecked(x: u64) -> Self {
63 Self(x)
64 }
65
66 pub fn from_u128(value: u128) -> Result<Self, err::Overflow> {
69 if value <= VARINT_MAX as u128 {
70 Ok(Self(value as _))
71 } else {
72 Err(err::Overflow { value })
73 }
74 }
75
76 pub const fn into_inner(self) -> u64 {
78 self.0
79 }
80
81 pub fn encoding_size(self) -> usize {
83 let x = self.0;
84 if x < (1 << 6) {
85 1
86 } else if x < (1 << 14) {
87 2
88 } else if x < (1 << 30) {
89 4
90 } else if x < (1 << 62) {
91 8
92 } else {
93 unreachable!("malformed VarInt");
94 }
95 }
96}
97
98impl From<VarInt> for u64 {
99 fn from(x: VarInt) -> Self {
100 x.0
101 }
102}
103
104impl From<u8> for VarInt {
105 fn from(x: u8) -> Self {
106 Self(x.into())
107 }
108}
109
110impl From<u16> for VarInt {
111 fn from(x: u16) -> Self {
112 Self(x.into())
113 }
114}
115
116impl From<u32> for VarInt {
117 fn from(x: u32) -> Self {
118 Self(x.into())
119 }
120}
121
122impl TryFrom<u128> for VarInt {
123 type Error = err::Overflow;
124
125 fn try_from(x: u128) -> Result<Self, Self::Error> {
126 Self::from_u128(x)
127 }
128}
129
130impl TryFrom<u64> for VarInt {
131 type Error = err::Overflow;
132
133 fn try_from(x: u64) -> Result<Self, Self::Error> {
135 Self::from_u64(x)
136 }
137}
138
139impl TryFrom<usize> for VarInt {
140 type Error = err::Overflow;
141
142 fn try_from(x: usize) -> Result<Self, Self::Error> {
144 Self::try_from(x as u64)
145 }
146}
147
148impl PartialEq<u64> for VarInt {
149 fn eq(&self, other: &u64) -> bool {
150 self.0.eq(other)
151 }
152}
153
154impl PartialOrd<u64> for VarInt {
155 fn partial_cmp(&self, other: &u64) -> Option<Ordering> {
156 self.0.partial_cmp(other)
157 }
158}
159
160impl fmt::Display for VarInt {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 self.0.fmt(f)
163 }
164}
165
166impl fmt::LowerHex for VarInt {
167 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168 self.0.fmt(f)
169 }
170}
171
172impl fmt::UpperHex for VarInt {
173 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174 self.0.fmt(f)
175 }
176}
177
178pub mod err {
180 use std::fmt;
181
182 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
184 pub struct Overflow {
185 pub(super) value: u128,
186 }
187
188 impl fmt::Display for Overflow {
189 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190 write!(f, "Value({}) too large for varint encoding", self.value)
191 }
192 }
193
194 impl std::error::Error for Overflow {}
195}
196
197pub fn be_varint(input: &[u8]) -> IResult<&[u8], VarInt> {
198 let (remain, first_byte) = be_u8(input)?;
199 let len = 2usize.pow((first_byte >> 6) as u32);
200 if remain.len() + 1 < len {
201 return Err(nom::Err::Incomplete(nom::Needed::new(
202 len - (remain.len() + 1),
203 )));
204 }
205
206 let mut buf = [0u8; 8];
207 buf[0] = first_byte & 0b0011_1111;
208 buf[1..len].copy_from_slice(&remain[..len - 1]);
209 let value = u64::from_be_bytes(buf) >> (8 * (8 - len));
210 Ok((&remain[len - 1..], VarInt(value)))
211}
212
213pub trait WriteVarInt {
214 fn put_varint(&mut self, value: VarInt);
215}
216
217impl<T: BufMut> WriteVarInt for T {
218 fn put_varint(&mut self, VarInt(x): VarInt) {
219 if x < 1u64 << 6 {
220 self.put_u8(x as u8);
221 } else if x < 1u64 << 14 {
222 self.put_u16((0b01 << 14) | x as u16);
223 } else if x < 1u64 << 30 {
224 self.put_u32((0b10 << 30) | x as u32);
225 } else if x < 1u64 << 62 {
226 self.put_u64((0b11 << 62) | x);
227 } else {
228 unreachable!("malformed VarInt")
229 };
230 }
231}
232
233#[allow(dead_code)]
234pub fn varint_from_u64(value: u64) -> IResult<&'static [u8], VarInt> {
235 match VarInt::from_u64(value) {
236 Ok(v) => Ok((&[] as &[u8], v)),
237 Err(_e) => Err(nom::Err::Error(make_error(
238 &[] as &[u8],
239 ErrorKind::TooLarge,
240 ))),
241 }
242}
243
244#[cfg(test)]
245mod tests {
246 use bytes::BytesMut;
247
248 use super::*;
249
250 fn roundtrip(v: u64) {
251 let v = VarInt::from_u64(v).unwrap();
252 let mut buf = BytesMut::new();
253 buf.put_varint(v);
254 assert_eq!(buf.len(), v.encoding_size());
255 let (remain, decoded) = be_varint(&buf).unwrap();
256 assert!(remain.is_empty());
257 assert_eq!(decoded, v);
258 }
259
260 #[test]
261 fn quic_varint_roundtrip() {
262 for v in [
263 0u64,
264 1,
265 63,
266 64,
267 16383,
268 16384,
269 (1 << 30) - 1,
270 1 << 30,
271 (1 << 62) - 1,
272 ] {
273 roundtrip(v);
274 }
275 }
276
277 #[test]
278 fn quic_varint_rejects_incomplete() {
279 let v = VarInt::from_u64(64).unwrap();
280 let mut buf = BytesMut::new();
281 buf.put_varint(v);
282 let truncated = &buf[..1];
283 match be_varint(truncated) {
284 Err(nom::Err::Incomplete(_)) => {}
285 other => panic!("expected Incomplete, got {other:?}"),
286 }
287 }
288
289 #[test]
290 fn quic_varint_overflow() {
291 assert!(VarInt::from_u64(VARINT_MAX + 1).is_err());
292 }
293}