net_wire/qpack/stream/decoder/
builder.rs1use core::fmt;
4
5use super::{QpackInsertCountIncrement, QpackSectionAcknowledgment, QpackStreamCancellation};
6use crate::qpack::integer::{
7 QPACK_INTEGER_MAX, QpackIntegerBuildError, canonical_encoded_len, integer_from_prevalidated,
8 write_canonical_prevalidated,
9};
10
11#[derive(Clone, Copy, Debug, Eq, PartialEq)]
13pub enum QpackDecoderInstructionBuildError {
14 SectionAcknowledgment(#[doc = "The nested stream-ID failure."] QpackIntegerBuildError),
16 StreamCancellation(#[doc = "The nested stream-ID failure."] QpackIntegerBuildError),
18 InsertCountIncrement(#[doc = "The nested increment failure."] QpackIntegerBuildError),
20 BufferTooShort {
22 required: usize,
24 available: usize,
26 },
27}
28
29impl fmt::Display for QpackDecoderInstructionBuildError {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 match self {
32 Self::SectionAcknowledgment(error) => {
33 write!(f, "QPACK Section Acknowledgment cannot be built: {error}")
34 }
35 Self::StreamCancellation(error) => {
36 write!(f, "QPACK Stream Cancellation cannot be built: {error}")
37 }
38 Self::InsertCountIncrement(error) => {
39 write!(f, "QPACK Insert Count Increment cannot be built: {error}")
40 }
41 Self::BufferTooShort {
42 required,
43 available,
44 } => write!(
45 f,
46 "QPACK decoder instruction buffer is too short: need {required} bytes, have {available}"
47 ),
48 }
49 }
50}
51
52pub struct QpackSectionAcknowledgmentBuilder<'a> {
54 destination: &'a mut [u8],
55 stream_id: u64,
56}
57
58impl<'a> QpackSectionAcknowledgmentBuilder<'a> {
59 pub fn new(destination: &'a mut [u8], stream_id: u64) -> Self {
61 Self {
62 destination,
63 stream_id,
64 }
65 }
66
67 pub fn build(
69 self,
70 ) -> Result<QpackSectionAcknowledgment<'a>, QpackDecoderInstructionBuildError> {
71 let length = integer_length(self.stream_id, 7)
72 .map_err(QpackDecoderInstructionBuildError::SectionAcknowledgment)?;
73 ensure_capacity(self.destination, length)?;
74 write_canonical_prevalidated(&mut self.destination[..length], 7, 0x80, self.stream_id);
75 let bytes = &self.destination[..length];
76 Ok(QpackSectionAcknowledgment {
77 bytes,
78 stream_id: integer_from_prevalidated(bytes, 7, 0x80, self.stream_id),
79 })
80 }
81}
82
83pub struct QpackStreamCancellationBuilder<'a> {
85 destination: &'a mut [u8],
86 stream_id: u64,
87}
88
89impl<'a> QpackStreamCancellationBuilder<'a> {
90 pub fn new(destination: &'a mut [u8], stream_id: u64) -> Self {
92 Self {
93 destination,
94 stream_id,
95 }
96 }
97
98 pub fn build(self) -> Result<QpackStreamCancellation<'a>, QpackDecoderInstructionBuildError> {
100 let length = integer_length(self.stream_id, 6)
101 .map_err(QpackDecoderInstructionBuildError::StreamCancellation)?;
102 ensure_capacity(self.destination, length)?;
103 write_canonical_prevalidated(&mut self.destination[..length], 6, 0x40, self.stream_id);
104 let bytes = &self.destination[..length];
105 Ok(QpackStreamCancellation {
106 bytes,
107 stream_id: integer_from_prevalidated(bytes, 6, 0x40, self.stream_id),
108 })
109 }
110}
111
112pub struct QpackInsertCountIncrementBuilder<'a> {
114 destination: &'a mut [u8],
115 increment: u64,
116}
117
118impl<'a> QpackInsertCountIncrementBuilder<'a> {
119 pub fn new(destination: &'a mut [u8], increment: u64) -> Self {
121 Self {
122 destination,
123 increment,
124 }
125 }
126
127 pub fn build(self) -> Result<QpackInsertCountIncrement<'a>, QpackDecoderInstructionBuildError> {
129 let length = integer_length(self.increment, 6)
130 .map_err(QpackDecoderInstructionBuildError::InsertCountIncrement)?;
131 ensure_capacity(self.destination, length)?;
132 write_canonical_prevalidated(&mut self.destination[..length], 6, 0, self.increment);
133 let bytes = &self.destination[..length];
134 Ok(QpackInsertCountIncrement {
135 bytes,
136 increment: integer_from_prevalidated(bytes, 6, 0, self.increment),
137 })
138 }
139}
140
141fn integer_length(value: u64, prefix_bits: u8) -> Result<usize, QpackIntegerBuildError> {
142 if value > QPACK_INTEGER_MAX {
143 return Err(QpackIntegerBuildError::ValueTooLarge { value });
144 }
145 Ok(canonical_encoded_len(value, prefix_bits))
146}
147
148fn ensure_capacity(
149 destination: &[u8],
150 required: usize,
151) -> Result<(), QpackDecoderInstructionBuildError> {
152 if destination.len() < required {
153 return Err(QpackDecoderInstructionBuildError::BufferTooShort {
154 required,
155 available: destination.len(),
156 });
157 }
158 Ok(())
159}