net_wire/qpack/field/section/
context.rs1use core::fmt;
4
5use super::prefix::QpackFieldSectionPrefix;
6
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9pub struct QpackFieldSectionContext {
10 required_insert_count: u64,
11 base: u64,
12}
13
14impl QpackFieldSectionContext {
15 pub fn decode(
17 prefix: QpackFieldSectionPrefix<'_>,
18 total_insert_count: u64,
19 maximum_table_capacity: u64,
20 ) -> Result<Self, QpackFieldSectionContextError> {
21 let required_insert_count = Self::reconstruct_required_insert_count(
22 prefix.encoded_required_insert_count().value(),
23 total_insert_count,
24 maximum_table_capacity,
25 )?;
26 let base = Self::resolve_base(
27 required_insert_count,
28 prefix.is_negative(),
29 prefix.delta_base().value(),
30 )?;
31 Ok(Self {
32 required_insert_count,
33 base,
34 })
35 }
36
37 pub fn reconstruct_required_insert_count(
39 encoded_required_insert_count: u64,
40 total_insert_count: u64,
41 maximum_table_capacity: u64,
42 ) -> Result<u64, QpackFieldSectionContextError> {
43 if encoded_required_insert_count == 0 {
44 return Ok(0);
45 }
46
47 let max_entries = maximum_table_capacity / 32;
48 if max_entries == 0 {
49 return Err(QpackFieldSectionContextError::ZeroMaximumEntries {
50 encoded_required_insert_count,
51 });
52 }
53 let full_range =
54 max_entries
55 .checked_mul(2)
56 .ok_or(QpackFieldSectionContextError::FullRangeOverflow {
57 maximum_table_capacity,
58 max_entries,
59 })?;
60 if encoded_required_insert_count > full_range {
61 return Err(
62 QpackFieldSectionContextError::EncodedRequiredInsertCountOutOfRange {
63 encoded_required_insert_count,
64 full_range,
65 },
66 );
67 }
68 let maximum_value = total_insert_count.checked_add(max_entries).ok_or(
69 QpackFieldSectionContextError::MaximumValueOverflow {
70 total_insert_count,
71 max_entries,
72 },
73 )?;
74 let max_wrapped_quotient = maximum_value / full_range;
75 let max_wrapped = max_wrapped_quotient.checked_mul(full_range).ok_or(
76 QpackFieldSectionContextError::RequiredInsertCountOverflow {
77 max_wrapped: max_wrapped_quotient,
78 encoded_required_insert_count,
79 },
80 )?;
81 let mut reconstructed = max_wrapped
82 .checked_add(encoded_required_insert_count - 1)
83 .ok_or(QpackFieldSectionContextError::RequiredInsertCountOverflow {
84 max_wrapped,
85 encoded_required_insert_count,
86 })?;
87 if reconstructed > maximum_value {
88 if reconstructed <= full_range {
89 return Err(QpackFieldSectionContextError::RequiredInsertCountTooOld {
90 reconstructed,
91 maximum_value,
92 full_range,
93 });
94 }
95 reconstructed = reconstructed.checked_sub(full_range).ok_or(
96 QpackFieldSectionContextError::RequiredInsertCountTooOld {
97 reconstructed,
98 maximum_value,
99 full_range,
100 },
101 )?;
102 }
103 if reconstructed == 0 {
104 return Err(QpackFieldSectionContextError::RequiredInsertCountZero);
105 }
106 Ok(reconstructed)
107 }
108
109 pub fn encode_required_insert_count(
111 required_insert_count: u64,
112 maximum_table_capacity: u64,
113 ) -> Result<u64, QpackFieldSectionContextError> {
114 if required_insert_count == 0 {
115 return Ok(0);
116 }
117
118 let max_entries = maximum_table_capacity / 32;
119 if max_entries == 0 {
120 return Err(QpackFieldSectionContextError::ZeroMaximumEntries {
121 encoded_required_insert_count: required_insert_count,
122 });
123 }
124 let full_range =
125 max_entries
126 .checked_mul(2)
127 .ok_or(QpackFieldSectionContextError::FullRangeOverflow {
128 maximum_table_capacity,
129 max_entries,
130 })?;
131 required_insert_count
132 .checked_rem(full_range)
133 .and_then(|count| count.checked_add(1))
134 .ok_or(QpackFieldSectionContextError::RequiredInsertCountOverflow {
135 max_wrapped: required_insert_count,
136 encoded_required_insert_count: required_insert_count,
137 })
138 }
139
140 pub fn resolve_base(
142 required_insert_count: u64,
143 negative: bool,
144 delta_base: u64,
145 ) -> Result<u64, QpackFieldSectionContextError> {
146 if negative {
147 if delta_base >= required_insert_count {
148 return Err(QpackFieldSectionContextError::BaseUnderflow {
149 required_insert_count,
150 delta_base,
151 });
152 }
153 required_insert_count
154 .checked_sub(delta_base)
155 .and_then(|base| base.checked_sub(1))
156 .ok_or(QpackFieldSectionContextError::BaseUnderflow {
157 required_insert_count,
158 delta_base,
159 })
160 } else {
161 required_insert_count.checked_add(delta_base).ok_or(
162 QpackFieldSectionContextError::BaseOverflow {
163 required_insert_count,
164 delta_base,
165 },
166 )
167 }
168 }
169
170 pub const fn required_insert_count(self) -> u64 {
172 self.required_insert_count
173 }
174
175 pub const fn base(self) -> u64 {
177 self.base
178 }
179}
180
181#[derive(Clone, Copy, Debug, Eq, PartialEq)]
183pub enum QpackFieldSectionContextError {
184 FullRangeOverflow {
186 maximum_table_capacity: u64,
188 max_entries: u64,
190 },
191 ZeroMaximumEntries {
193 encoded_required_insert_count: u64,
195 },
196 EncodedRequiredInsertCountOutOfRange {
198 encoded_required_insert_count: u64,
200 full_range: u64,
202 },
203 MaximumValueOverflow {
205 total_insert_count: u64,
207 max_entries: u64,
209 },
210 RequiredInsertCountOverflow {
212 max_wrapped: u64,
214 encoded_required_insert_count: u64,
216 },
217 RequiredInsertCountTooOld {
219 reconstructed: u64,
221 maximum_value: u64,
223 full_range: u64,
225 },
226 RequiredInsertCountZero,
228 BaseOverflow {
230 required_insert_count: u64,
232 delta_base: u64,
234 },
235 BaseUnderflow {
237 required_insert_count: u64,
239 delta_base: u64,
241 },
242}
243
244impl fmt::Display for QpackFieldSectionContextError {
245 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
246 match self {
247 Self::FullRangeOverflow {
248 maximum_table_capacity,
249 max_entries,
250 } => write!(
251 formatter,
252 "QPACK full range overflows u64 for maximum table capacity {maximum_table_capacity} and maximum entries {max_entries}"
253 ),
254 Self::ZeroMaximumEntries {
255 encoded_required_insert_count,
256 } => write!(
257 formatter,
258 "QPACK Required Insert Count {encoded_required_insert_count} is nonzero with zero maximum entries"
259 ),
260 Self::EncodedRequiredInsertCountOutOfRange {
261 encoded_required_insert_count,
262 full_range,
263 } => write!(
264 formatter,
265 "QPACK Encoded Required Insert Count {encoded_required_insert_count} exceeds full range {full_range}"
266 ),
267 Self::MaximumValueOverflow {
268 total_insert_count,
269 max_entries,
270 } => write!(
271 formatter,
272 "QPACK maximum Required Insert Count overflows u64 for insert count {total_insert_count} and maximum entries {max_entries}"
273 ),
274 Self::RequiredInsertCountOverflow {
275 max_wrapped,
276 encoded_required_insert_count,
277 } => write!(
278 formatter,
279 "QPACK Required Insert Count overflows u64 for wrapped value {max_wrapped} and count {encoded_required_insert_count}"
280 ),
281 Self::RequiredInsertCountTooOld {
282 reconstructed,
283 maximum_value,
284 full_range,
285 } => write!(
286 formatter,
287 "QPACK Required Insert Count {reconstructed} exceeds maximum {maximum_value} for full range {full_range}"
288 ),
289 Self::RequiredInsertCountZero => formatter
290 .write_str("QPACK nonzero Encoded Required Insert Count reconstructed to zero"),
291 Self::BaseOverflow {
292 required_insert_count,
293 delta_base,
294 } => write!(
295 formatter,
296 "QPACK Base overflows u64 for Required Insert Count {required_insert_count} and Delta Base {delta_base}"
297 ),
298 Self::BaseUnderflow {
299 required_insert_count,
300 delta_base,
301 } => write!(
302 formatter,
303 "QPACK Base underflows u64 for Required Insert Count {required_insert_count} and Delta Base {delta_base}"
304 ),
305 }
306 }
307}
308
309impl core::error::Error for QpackFieldSectionContextError {}