Skip to main content

net_wire/quic/
varint.rs

1//! RFC 9000 section 16 variable-length integer parsing and construction.
2
3use core::fmt;
4
5const MAX_VALUE: u64 = (1 << 62) - 1;
6
7/// Failure to parse a QUIC variable-length integer.
8#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9pub enum QuicVarIntParseError {
10    /// The input does not contain the complete encoded integer.
11    Incomplete {
12        /// Bytes required by the encoded width.
13        required: usize,
14        /// Bytes available in the input.
15        available: usize,
16    },
17}
18
19impl fmt::Display for QuicVarIntParseError {
20    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21        match self {
22            Self::Incomplete {
23                required,
24                available,
25            } => write!(
26                f,
27                "QUIC variable-length integer input is incomplete: need {required} bytes, have {available}"
28            ),
29        }
30    }
31}
32
33/// A QUIC variable-integer encoded width.
34#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
35pub enum QuicVarIntLen {
36    /// One encoded byte, carrying up to 6 value bits.
37    One,
38    /// Two encoded bytes, carrying up to 14 value bits.
39    Two,
40    /// Four encoded bytes, carrying up to 30 value bits.
41    Four,
42    /// Eight encoded bytes, carrying up to 62 value bits.
43    Eight,
44}
45
46impl QuicVarIntLen {
47    /// Returns the encoded width in bytes.
48    pub const fn byte_len(self) -> usize {
49        match self {
50            Self::One => 1,
51            Self::Two => 2,
52            Self::Four => 4,
53            Self::Eight => 8,
54        }
55    }
56
57    /// Returns the greatest value representable at this encoded width.
58    pub const fn max_value(self) -> u64 {
59        match self {
60            Self::One => 63,
61            Self::Two => 16_383,
62            Self::Four => 1_073_741_823,
63            Self::Eight => MAX_VALUE,
64        }
65    }
66
67    const fn prefix(self) -> u8 {
68        match self {
69            Self::One => 0b00,
70            Self::Two => 0b01,
71            Self::Four => 0b10,
72            Self::Eight => 0b11,
73        }
74    }
75
76    const fn from_first_byte(first: u8) -> Self {
77        match first >> 6 {
78            0 => Self::One,
79            1 => Self::Two,
80            2 => Self::Four,
81            _ => Self::Eight,
82        }
83    }
84}
85
86/// Failure to build a QUIC variable-length integer.
87#[derive(Clone, Copy, Debug, Eq, PartialEq)]
88pub enum QuicVarIntBuildError {
89    /// The value exceeds QUIC's 62-bit maximum.
90    ValueTooLarge {
91        /// Supplied value.
92        value: u64,
93    },
94    /// The requested encoded width cannot represent the value.
95    WidthTooSmall {
96        /// Requested encoded width.
97        length: QuicVarIntLen,
98        /// Supplied value.
99        value: u64,
100    },
101    /// The caller buffer cannot contain the requested encoding.
102    BufferTooShort {
103        /// Required bytes.
104        required: usize,
105        /// Available bytes.
106        available: usize,
107    },
108}
109
110impl fmt::Display for QuicVarIntBuildError {
111    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112        match self {
113            Self::ValueTooLarge { value } => write!(
114                f,
115                "QUIC variable-length integer value {value} exceeds the 62-bit maximum"
116            ),
117            Self::WidthTooSmall { length, value } => write!(
118                f,
119                "QUIC variable-length integer width {} cannot represent {value}",
120                length.byte_len()
121            ),
122            Self::BufferTooShort {
123                required,
124                available,
125            } => write!(
126                f,
127                "QUIC variable-length integer buffer is too short: need {required} bytes, have {available}"
128            ),
129        }
130    }
131}
132
133/// An exact borrowed RFC 9000 section 16 variable-integer representation.
134#[derive(Clone, Copy, Debug, Eq, PartialEq)]
135pub struct QuicVarInt<'a> {
136    bytes: &'a [u8],
137    value: u64,
138    length: QuicVarIntLen,
139}
140
141impl<'a> QuicVarInt<'a> {
142    /// Assembles a variable-integer view from builder-validated wire components.
143    pub(crate) const fn from_validated(bytes: &'a [u8], value: u64, length: QuicVarIntLen) -> Self {
144        Self {
145            bytes,
146            value,
147            length,
148        }
149    }
150
151    /// Parses one variable-length integer and excludes all following input bytes.
152    pub fn parse(bytes: &'a [u8]) -> Result<Self, QuicVarIntParseError> {
153        let first = *bytes.first().ok_or(QuicVarIntParseError::Incomplete {
154            required: 1,
155            available: 0,
156        })?;
157        let length = QuicVarIntLen::from_first_byte(first);
158        let required = length.byte_len();
159        if bytes.len() < required {
160            return Err(QuicVarIntParseError::Incomplete {
161                required,
162                available: bytes.len(),
163            });
164        }
165
166        let exact = &bytes[..required];
167        let mut value = u64::from(exact[0] & 0x3f);
168        let mut index = 1;
169        while index < required {
170            value = (value << 8) | u64::from(exact[index]);
171            index += 1;
172        }
173        Ok(Self {
174            bytes: exact,
175            value,
176            length,
177        })
178    }
179
180    /// Returns the decoded integer value.
181    pub const fn value(self) -> u64 {
182        self.value
183    }
184
185    /// Returns the exact encoded bytes, excluding any following input bytes.
186    pub const fn as_bytes(self) -> &'a [u8] {
187        self.bytes
188    }
189
190    /// Returns the encoded width.
191    pub const fn encoded_len(self) -> QuicVarIntLen {
192        self.length
193    }
194
195    /// Returns the encoded length in bytes.
196    pub const fn byte_len(self) -> usize {
197        self.length.byte_len()
198    }
199
200    /// Returns whether this uses the canonical shortest width for its value.
201    pub const fn is_canonical(self) -> bool {
202        self.length as u8 == canonical_len(self.value) as u8
203    }
204}
205
206/// Builds a QUIC variable-length integer in caller-owned storage.
207pub struct QuicVarIntBuilder<'a> {
208    destination: &'a mut [u8],
209    value: u64,
210    length: Option<QuicVarIntLen>,
211}
212
213impl<'a> QuicVarIntBuilder<'a> {
214    /// Creates a builder that emits the value with its canonical shortest width.
215    pub fn new(destination: &'a mut [u8], value: u64) -> Self {
216        Self {
217            destination,
218            value,
219            length: None,
220        }
221    }
222
223    /// Requests an explicit legal encoded width, including a non-canonical width.
224    pub fn with_len(mut self, length: QuicVarIntLen) -> Self {
225        self.length = Some(length);
226        self
227    }
228
229    /// Validates the value, requested width, and capacity before mutating the destination.
230    pub fn build(self) -> Result<QuicVarInt<'a>, QuicVarIntBuildError> {
231        if self.value > MAX_VALUE {
232            return Err(QuicVarIntBuildError::ValueTooLarge { value: self.value });
233        }
234        let length = self.length.unwrap_or(canonical_len(self.value));
235        if self.value > length.max_value() {
236            return Err(QuicVarIntBuildError::WidthTooSmall {
237                length,
238                value: self.value,
239            });
240        }
241        let required = length.byte_len();
242        if self.destination.len() < required {
243            return Err(QuicVarIntBuildError::BufferTooShort {
244                required,
245                available: self.destination.len(),
246            });
247        }
248
249        let exact = &mut self.destination[..required];
250        let value_bytes = self.value.to_be_bytes();
251        exact.copy_from_slice(&value_bytes[value_bytes.len() - required..]);
252        exact[0] |= length.prefix() << 6;
253        Ok(QuicVarInt {
254            bytes: exact,
255            value: self.value,
256            length,
257        })
258    }
259}
260
261const fn canonical_len(value: u64) -> QuicVarIntLen {
262    if value <= QuicVarIntLen::One.max_value() {
263        QuicVarIntLen::One
264    } else if value <= QuicVarIntLen::Two.max_value() {
265        QuicVarIntLen::Two
266    } else if value <= QuicVarIntLen::Four.max_value() {
267        QuicVarIntLen::Four
268    } else {
269        QuicVarIntLen::Eight
270    }
271}