1use core::fmt;
4
5const MAX_VALUE: u64 = (1 << 62) - 1;
6
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9pub enum QuicVarIntParseError {
10 Incomplete {
12 required: usize,
14 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#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
35pub enum QuicVarIntLen {
36 One,
38 Two,
40 Four,
42 Eight,
44}
45
46impl QuicVarIntLen {
47 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 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#[derive(Clone, Copy, Debug, Eq, PartialEq)]
88pub enum QuicVarIntBuildError {
89 ValueTooLarge {
91 value: u64,
93 },
94 WidthTooSmall {
96 length: QuicVarIntLen,
98 value: u64,
100 },
101 BufferTooShort {
103 required: usize,
105 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#[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 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 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 pub const fn value(self) -> u64 {
182 self.value
183 }
184
185 pub const fn as_bytes(self) -> &'a [u8] {
187 self.bytes
188 }
189
190 pub const fn encoded_len(self) -> QuicVarIntLen {
192 self.length
193 }
194
195 pub const fn byte_len(self) -> usize {
197 self.length.byte_len()
198 }
199
200 pub const fn is_canonical(self) -> bool {
202 self.length as u8 == canonical_len(self.value) as u8
203 }
204}
205
206pub struct QuicVarIntBuilder<'a> {
208 destination: &'a mut [u8],
209 value: u64,
210 length: Option<QuicVarIntLen>,
211}
212
213impl<'a> QuicVarIntBuilder<'a> {
214 pub fn new(destination: &'a mut [u8], value: u64) -> Self {
216 Self {
217 destination,
218 value,
219 length: None,
220 }
221 }
222
223 pub fn with_len(mut self, length: QuicVarIntLen) -> Self {
225 self.length = Some(length);
226 self
227 }
228
229 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}