net_wire/qpack/state/
decoder.rs1use core::fmt;
8
9use crate::qpack::field::section::decode::QpackDecodedFieldSection;
10use crate::qpack::integer::QPACK_INTEGER_MAX;
11use crate::qpack::stream::decoder::{
12 QpackDecoderInstructionBuildError, QpackInsertCountIncrement, QpackInsertCountIncrementBuilder,
13 QpackSectionAcknowledgment, QpackSectionAcknowledgmentBuilder, QpackStreamCancellation,
14 QpackStreamCancellationBuilder,
15};
16
17#[derive(Clone, Copy, Debug, Eq, PartialEq)]
23pub struct QpackDecoderState {
24 known_received_count: u64,
25}
26
27impl QpackDecoderState {
28 pub const fn new() -> Self {
30 Self {
31 known_received_count: 0,
32 }
33 }
34
35 pub const fn known_received_count(&self) -> u64 {
37 self.known_received_count
38 }
39
40 pub fn acknowledge_field_section<'a>(
48 &mut self,
49 destination: &'a mut [u8],
50 stream_id: u64,
51 section: QpackDecodedFieldSection<'_>,
52 ) -> Result<Option<QpackSectionAcknowledgment<'a>>, QpackDecoderFeedbackError> {
53 if !section.contains_dynamic_references() {
54 return Ok(None);
55 }
56
57 let required_insert_count = section.required_insert_count();
58 let acknowledgment = QpackSectionAcknowledgmentBuilder::new(destination, stream_id)
59 .build()
60 .map_err(QpackDecoderFeedbackError::InstructionBuild)?;
61 self.known_received_count = self.known_received_count.max(required_insert_count);
62 Ok(Some(acknowledgment))
63 }
64
65 pub fn cancel_stream<'a>(
70 &mut self,
71 destination: &'a mut [u8],
72 stream_id: u64,
73 ) -> Result<QpackStreamCancellation<'a>, QpackDecoderFeedbackError> {
74 QpackStreamCancellationBuilder::new(destination, stream_id)
75 .build()
76 .map_err(QpackDecoderFeedbackError::InstructionBuild)
77 }
78
79 pub fn emit_insert_count_increment<'a>(
86 &mut self,
87 destination: &'a mut [u8],
88 decoder_insert_count: u64,
89 ) -> Result<Option<QpackInsertCountIncrement<'a>>, QpackDecoderFeedbackError> {
90 if decoder_insert_count == self.known_received_count {
91 return Ok(None);
92 }
93 if decoder_insert_count < self.known_received_count {
94 return Err(QpackDecoderFeedbackError::InsertCountRegression {
95 known_received_count: self.known_received_count,
96 decoder_insert_count,
97 });
98 }
99
100 let increment = core::cmp::min(
101 decoder_insert_count - self.known_received_count,
102 QPACK_INTEGER_MAX,
103 );
104 let advanced_count = self.known_received_count.checked_add(increment).ok_or(
105 QpackDecoderFeedbackError::InsertCountAdvanceOverflow {
106 known_received_count: self.known_received_count,
107 increment,
108 },
109 )?;
110 let instruction = QpackInsertCountIncrementBuilder::new(destination, increment)
111 .build()
112 .map_err(QpackDecoderFeedbackError::InstructionBuild)?;
113 self.known_received_count = advanced_count;
114 Ok(Some(instruction))
115 }
116}
117
118impl Default for QpackDecoderState {
119 fn default() -> Self {
120 Self::new()
121 }
122}
123
124#[derive(Clone, Copy, Debug, Eq, PartialEq)]
126pub enum QpackDecoderFeedbackError {
127 InsertCountRegression {
129 known_received_count: u64,
131 decoder_insert_count: u64,
133 },
134 InsertCountAdvanceOverflow {
136 known_received_count: u64,
138 increment: u64,
140 },
141 InstructionBuild(
143 #[doc = "The nested local instruction build failure."] QpackDecoderInstructionBuildError,
144 ),
145}
146
147impl QpackDecoderFeedbackError {
148 pub const fn is_provisioning_error(self) -> bool {
150 matches!(
151 self,
152 Self::InstructionBuild(QpackDecoderInstructionBuildError::BufferTooShort { .. })
153 )
154 }
155}
156
157impl fmt::Display for QpackDecoderFeedbackError {
158 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
159 match self {
160 Self::InsertCountRegression {
161 known_received_count,
162 decoder_insert_count,
163 } => write!(
164 formatter,
165 "decoder insert count {decoder_insert_count} regresses below Known Received Count {known_received_count}"
166 ),
167 Self::InsertCountAdvanceOverflow {
168 known_received_count,
169 increment,
170 } => write!(
171 formatter,
172 "Known Received Count {known_received_count} cannot advance by {increment}"
173 ),
174 Self::InstructionBuild(error) => write!(
175 formatter,
176 "QPACK decoder feedback instruction cannot be built: {error}"
177 ),
178 }
179 }
180}
181
182impl core::error::Error for QpackDecoderFeedbackError {}