Skip to main content

moqtap_codec/
varint.rs

1use bytes::{Buf, BufMut};
2
3/// Maximum varint value: 2^62 - 1 (RFC 9000 Section 16)
4pub const MAX_VARINT: u64 = 4_611_686_018_427_387_903;
5
6/// A QUIC variable-length integer (RFC 9000 Section 16).
7///
8/// Uses 2-bit prefix encoding:
9/// - 00: 1 byte, values 0-63
10/// - 01: 2 bytes, values 0-16383
11/// - 10: 4 bytes, values 0-1073741823
12/// - 11: 8 bytes, values 0-4611686018427387903
13#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub struct VarInt(u64);
15
16#[derive(Debug, thiserror::Error, PartialEq, Eq, Clone)]
17pub enum VarIntError {
18    #[error("value {0} exceeds maximum varint value (2^62 - 1)")]
19    Overflow(u64),
20    #[error("insufficient bytes for varint decoding")]
21    UnexpectedEnd,
22}
23
24impl VarInt {
25    /// Create a VarInt from a u64, returning an error if it exceeds the maximum.
26    pub fn from_u64(v: u64) -> Result<Self, VarIntError> {
27        if v > MAX_VARINT {
28            Err(VarIntError::Overflow(v))
29        } else {
30            Ok(VarInt(v))
31        }
32    }
33
34    /// Get the inner u64 value.
35    pub fn into_inner(self) -> u64 {
36        self.0
37    }
38
39    /// Return the number of bytes needed to encode this varint.
40    pub fn encoded_len(&self) -> usize {
41        if self.0 <= 63 {
42            1
43        } else if self.0 <= 16383 {
44            2
45        } else if self.0 <= 1073741823 {
46            4
47        } else {
48            8
49        }
50    }
51
52    /// Encode this varint into the given buffer.
53    pub fn encode(&self, buf: &mut impl BufMut) {
54        match self.encoded_len() {
55            1 => {
56                buf.put_u8(self.0 as u8);
57            }
58            2 => {
59                buf.put_u16((self.0 as u16) | 0x4000);
60            }
61            4 => {
62                buf.put_u32((self.0 as u32) | 0x80000000);
63            }
64            8 => {
65                buf.put_u64(self.0 | 0xC000000000000000);
66            }
67            _ => unreachable!(),
68        }
69    }
70
71    /// Decode a varint from the given buffer.
72    pub fn decode(buf: &mut impl Buf) -> Result<Self, VarIntError> {
73        if buf.remaining() < 1 {
74            return Err(VarIntError::UnexpectedEnd);
75        }
76        let first = buf.chunk()[0];
77        let prefix = first >> 6;
78        let len = 1usize << prefix;
79        if buf.remaining() < len {
80            return Err(VarIntError::UnexpectedEnd);
81        }
82        let val = match len {
83            1 => {
84                buf.advance(1);
85                (first & 0x3F) as u64
86            }
87            2 => {
88                let v = buf.get_u16();
89                (v & 0x3FFF) as u64
90            }
91            4 => {
92                let v = buf.get_u32();
93                (v & 0x3FFFFFFF) as u64
94            }
95            8 => {
96                let v = buf.get_u64();
97                v & 0x3FFFFFFFFFFFFFFF
98            }
99            _ => unreachable!(),
100        };
101        Ok(VarInt(val))
102    }
103}
104
105impl TryFrom<u64> for VarInt {
106    type Error = VarIntError;
107    fn try_from(v: u64) -> Result<Self, Self::Error> {
108        Self::from_u64(v)
109    }
110}
111
112impl From<VarInt> for u64 {
113    fn from(v: VarInt) -> u64 {
114        v.0
115    }
116}
117
118impl From<u32> for VarInt {
119    fn from(v: u32) -> Self {
120        VarInt(v as u64)
121    }
122}