1use core::fmt;
6
7use crate::quic::varint::{
8 QuicVarInt, QuicVarIntBuildError, QuicVarIntBuilder, QuicVarIntLen, QuicVarIntParseError,
9};
10
11use super::super::codepoints::Http3FrameType;
12
13#[derive(Clone, Copy, Debug, Eq, PartialEq)]
15pub enum Http3FrameParseError {
16 TypeVarInt(QuicVarIntParseError),
18 LengthVarInt(QuicVarIntParseError),
20 PayloadLengthNotRepresentable {
22 value: u64,
24 },
25 FrameLengthOverflow {
27 type_length: usize,
29 length_length: usize,
31 payload_length: usize,
33 },
34 PayloadTooLarge {
36 maximum: usize,
38 actual: usize,
40 },
41 IncompletePayload {
43 required: usize,
45 available: usize,
47 },
48}
49
50impl fmt::Display for Http3FrameParseError {
51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52 match self {
53 Self::TypeVarInt(error) => {
54 write!(f, "HTTP/3 frame type variable-length integer: {error}")
55 }
56 Self::LengthVarInt(error) => {
57 write!(
58 f,
59 "HTTP/3 frame payload length variable-length integer: {error}"
60 )
61 }
62 Self::PayloadLengthNotRepresentable { value } => write!(
63 f,
64 "HTTP/3 frame payload length {value} cannot be represented as usize"
65 ),
66 Self::FrameLengthOverflow {
67 type_length,
68 length_length,
69 payload_length,
70 } => write!(
71 f,
72 "HTTP/3 frame length overflows: type {type_length} bytes, length {length_length} bytes, payload {payload_length} bytes"
73 ),
74 Self::PayloadTooLarge { maximum, actual } => write!(
75 f,
76 "HTTP/3 frame payload is too large: maximum {maximum}, got {actual}"
77 ),
78 Self::IncompletePayload {
79 required,
80 available,
81 } => write!(
82 f,
83 "HTTP/3 frame payload is incomplete: need {required} bytes, have {available}"
84 ),
85 }
86 }
87}
88
89impl core::error::Error for Http3FrameParseError {}
90
91#[derive(Clone, Copy, Debug, Eq, PartialEq)]
93pub struct Http3Frame<'a> {
94 bytes: &'a [u8],
95 frame_type: QuicVarInt<'a>,
96 payload_length: QuicVarInt<'a>,
97}
98
99impl<'a> Http3Frame<'a> {
100 pub(super) fn from_validated(
101 bytes: &'a [u8],
102 frame_type_value: u64,
103 frame_type_length: QuicVarIntLen,
104 payload_length_value: u64,
105 payload_length_length: QuicVarIntLen,
106 ) -> Self {
107 let type_end = frame_type_length.byte_len();
108 let length_end = type_end + payload_length_length.byte_len();
109 Self {
110 bytes,
111 frame_type: QuicVarInt::from_validated(
112 &bytes[..type_end],
113 frame_type_value,
114 frame_type_length,
115 ),
116 payload_length: QuicVarInt::from_validated(
117 &bytes[type_end..length_end],
118 payload_length_value,
119 payload_length_length,
120 ),
121 }
122 }
123
124 pub fn parse(bytes: &'a [u8], maximum_payload: usize) -> Result<Self, Http3FrameParseError> {
126 let frame_type = QuicVarInt::parse(bytes).map_err(Http3FrameParseError::TypeVarInt)?;
127 let type_length = frame_type.byte_len();
128 let payload_length =
129 QuicVarInt::parse(&bytes[type_length..]).map_err(Http3FrameParseError::LengthVarInt)?;
130 let total_length = frame_length(
131 type_length,
132 payload_length.byte_len(),
133 payload_length.value(),
134 maximum_payload,
135 bytes.len(),
136 )?;
137 Ok(Self {
138 bytes: &bytes[..total_length],
139 frame_type,
140 payload_length,
141 })
142 }
143
144 pub const fn frame_type(&self) -> Http3FrameType {
146 Http3FrameType::new(self.frame_type.value())
147 }
148
149 pub const fn frame_type_varint(&self) -> QuicVarInt<'a> {
151 self.frame_type
152 }
153
154 pub const fn payload_length_varint(&self) -> QuicVarInt<'a> {
156 self.payload_length
157 }
158
159 pub fn payload_length(&self) -> usize {
161 self.payload().len()
162 }
163
164 pub fn payload(&self) -> &'a [u8] {
166 &self.bytes[self.frame_type.byte_len() + self.payload_length.byte_len()..]
167 }
168
169 pub const fn as_bytes(&self) -> &'a [u8] {
171 self.bytes
172 }
173}
174
175#[derive(Debug, Eq, PartialEq)]
177pub struct Http3FrameMut<'a> {
178 bytes: &'a mut [u8],
179 frame_type: Http3FrameType,
180 payload_offset: usize,
181}
182
183impl<'a> Http3FrameMut<'a> {
184 pub fn parse(
186 bytes: &'a mut [u8],
187 maximum_payload: usize,
188 ) -> Result<Self, Http3FrameParseError> {
189 let (frame_type, payload_offset, total_length) = frame_layout(bytes, maximum_payload)?;
190 Ok(Self {
191 bytes: &mut bytes[..total_length],
192 frame_type,
193 payload_offset,
194 })
195 }
196
197 pub const fn frame_type(&self) -> Http3FrameType {
199 self.frame_type
200 }
201
202 pub fn payload_length(&self) -> usize {
204 self.bytes.len() - self.payload_offset
205 }
206
207 pub fn payload(&self) -> &[u8] {
209 &self.bytes[self.payload_offset..]
210 }
211
212 pub fn payload_mut(&mut self) -> &mut [u8] {
214 &mut self.bytes[self.payload_offset..]
215 }
216
217 pub fn as_bytes(&self) -> &[u8] {
219 self.bytes
220 }
221}
222
223fn frame_layout(
224 bytes: &[u8],
225 maximum_payload: usize,
226) -> Result<(Http3FrameType, usize, usize), Http3FrameParseError> {
227 let frame_type = QuicVarInt::parse(bytes).map_err(Http3FrameParseError::TypeVarInt)?;
228 let type_length = frame_type.byte_len();
229 let payload_length =
230 QuicVarInt::parse(&bytes[type_length..]).map_err(Http3FrameParseError::LengthVarInt)?;
231 let payload_offset = type_length + payload_length.byte_len();
232 let total_length = frame_length(
233 type_length,
234 payload_length.byte_len(),
235 payload_length.value(),
236 maximum_payload,
237 bytes.len(),
238 )?;
239 Ok((
240 Http3FrameType::new(frame_type.value()),
241 payload_offset,
242 total_length,
243 ))
244}
245
246fn frame_length(
247 type_length: usize,
248 length_length: usize,
249 payload_length_value: u64,
250 maximum_payload: usize,
251 available: usize,
252) -> Result<usize, Http3FrameParseError> {
253 let payload_length = usize::try_from(payload_length_value).map_err(|_| {
254 Http3FrameParseError::PayloadLengthNotRepresentable {
255 value: payload_length_value,
256 }
257 })?;
258 if payload_length > maximum_payload {
259 return Err(Http3FrameParseError::PayloadTooLarge {
260 maximum: maximum_payload,
261 actual: payload_length,
262 });
263 }
264 let header_length = type_length.checked_add(length_length).ok_or(
265 Http3FrameParseError::FrameLengthOverflow {
266 type_length,
267 length_length,
268 payload_length,
269 },
270 )?;
271 let required = header_length.checked_add(payload_length).ok_or(
272 Http3FrameParseError::FrameLengthOverflow {
273 type_length,
274 length_length,
275 payload_length,
276 },
277 )?;
278 if available < required {
279 return Err(Http3FrameParseError::IncompletePayload {
280 required,
281 available,
282 });
283 }
284 Ok(required)
285}
286
287#[derive(Clone, Copy, Debug, Eq, PartialEq)]
289pub enum Http3FrameBuildError {
290 TypeVarInt(QuicVarIntBuildError),
292 LengthVarInt(QuicVarIntBuildError),
294 PayloadLengthNotRepresentable {
296 length: usize,
298 },
299 FrameLengthOverflow {
301 type_length: usize,
303 length_length: usize,
305 payload_length: usize,
307 },
308 BufferTooShort {
310 required: usize,
312 available: usize,
314 },
315}
316
317impl fmt::Display for Http3FrameBuildError {
318 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
319 match self {
320 Self::TypeVarInt(error) => {
321 write!(f, "HTTP/3 frame type variable-length integer: {error}")
322 }
323 Self::LengthVarInt(error) => {
324 write!(
325 f,
326 "HTTP/3 frame payload length variable-length integer: {error}"
327 )
328 }
329 Self::PayloadLengthNotRepresentable { length } => write!(
330 f,
331 "HTTP/3 frame payload length {length} cannot be represented as u64"
332 ),
333 Self::FrameLengthOverflow {
334 type_length,
335 length_length,
336 payload_length,
337 } => write!(
338 f,
339 "HTTP/3 frame length overflows: type {type_length} bytes, length {length_length} bytes, payload {payload_length} bytes"
340 ),
341 Self::BufferTooShort {
342 required,
343 available,
344 } => write!(
345 f,
346 "HTTP/3 frame destination is too short: need {required} bytes, have {available}"
347 ),
348 }
349 }
350}
351
352impl core::error::Error for Http3FrameBuildError {}
353
354pub(crate) struct Http3FrameEnvelopePlan {
356 frame_type: Http3FrameType,
357 payload_length: u64,
358 type_bytes: [u8; 8],
359 type_length: QuicVarIntLen,
360 length_bytes: [u8; 8],
361 length_length: QuicVarIntLen,
362 header_length: usize,
363 required: usize,
364}
365
366impl Http3FrameEnvelopePlan {
367 pub(crate) fn new(
369 frame_type: Http3FrameType,
370 payload_length: usize,
371 available: usize,
372 ) -> Result<Self, Http3FrameBuildError> {
373 let payload_length_value = u64::try_from(payload_length).map_err(|_| {
374 Http3FrameBuildError::PayloadLengthNotRepresentable {
375 length: payload_length,
376 }
377 })?;
378 let mut type_bytes = [0; 8];
379 let type_varint = QuicVarIntBuilder::new(&mut type_bytes, frame_type.value())
380 .build()
381 .map_err(Http3FrameBuildError::TypeVarInt)?;
382 let mut length_bytes = [0; 8];
383 let length_varint = QuicVarIntBuilder::new(&mut length_bytes, payload_length_value)
384 .build()
385 .map_err(Http3FrameBuildError::LengthVarInt)?;
386 let type_length = type_varint.encoded_len();
387 let length_length = length_varint.encoded_len();
388 let header_length = type_length
389 .byte_len()
390 .checked_add(length_length.byte_len())
391 .ok_or(Http3FrameBuildError::FrameLengthOverflow {
392 type_length: type_length.byte_len(),
393 length_length: length_length.byte_len(),
394 payload_length,
395 })?;
396 let required = header_length.checked_add(payload_length).ok_or(
397 Http3FrameBuildError::FrameLengthOverflow {
398 type_length: type_length.byte_len(),
399 length_length: length_length.byte_len(),
400 payload_length,
401 },
402 )?;
403 if available < required {
404 return Err(Http3FrameBuildError::BufferTooShort {
405 required,
406 available,
407 });
408 }
409 Ok(Self {
410 frame_type,
411 payload_length: payload_length_value,
412 type_bytes,
413 type_length,
414 length_bytes,
415 length_length,
416 header_length,
417 required,
418 })
419 }
420
421 pub(crate) const fn header_length(&self) -> usize {
423 self.header_length
424 }
425
426 pub(crate) const fn required(&self) -> usize {
428 self.required
429 }
430
431 pub(crate) fn write_header(&self, destination: &mut [u8]) {
433 let type_length = self.type_length.byte_len();
434 destination[..type_length].copy_from_slice(&self.type_bytes[..type_length]);
435 destination[type_length..self.header_length]
436 .copy_from_slice(&self.length_bytes[..self.length_length.byte_len()]);
437 }
438
439 pub(crate) fn finish<'output>(self, bytes: &'output mut [u8]) -> Http3Frame<'output> {
441 Http3Frame::from_validated(
442 bytes,
443 self.frame_type.value(),
444 self.type_length,
445 self.payload_length,
446 self.length_length,
447 )
448 }
449}
450
451pub struct Http3FrameBuilder<'output, 'payload> {
453 destination: &'output mut [u8],
454 frame_type: Http3FrameType,
455 payload: &'payload [u8],
456}
457
458impl<'output, 'payload> Http3FrameBuilder<'output, 'payload> {
459 pub fn new(
461 destination: &'output mut [u8],
462 frame_type: Http3FrameType,
463 payload: &'payload [u8],
464 ) -> Self {
465 Self {
466 destination,
467 frame_type,
468 payload,
469 }
470 }
471
472 pub fn build(self) -> Result<Http3Frame<'output>, Http3FrameBuildError> {
474 let plan = Http3FrameEnvelopePlan::new(
475 self.frame_type,
476 self.payload.len(),
477 self.destination.len(),
478 )?;
479 let required = plan.required();
480 let header_length = plan.header_length();
481 let bytes = &mut self.destination[..required];
482 plan.write_header(bytes);
483 bytes[header_length..].copy_from_slice(self.payload);
484 Ok(plan.finish(bytes))
485 }
486}