quiche/h3/qpack/
decoder.rs1use super::Error;
28use super::Result;
29
30use crate::h3::Header;
31
32use super::INDEXED;
33use super::INDEXED_WITH_POST_BASE;
34use super::LITERAL;
35use super::LITERAL_WITH_NAME_REF;
36
37#[derive(Clone, Copy, Debug, PartialEq)]
38enum Representation {
39 Indexed,
40 IndexedWithPostBase,
41 Literal,
42 LiteralWithNameRef,
43 LiteralWithPostBase,
44}
45
46impl Representation {
47 pub fn from_byte(b: u8) -> Representation {
48 if b & INDEXED == INDEXED {
49 return Representation::Indexed;
50 }
51
52 if b & LITERAL_WITH_NAME_REF == LITERAL_WITH_NAME_REF {
53 return Representation::LiteralWithNameRef;
54 }
55
56 if b & LITERAL == LITERAL {
57 return Representation::Literal;
58 }
59
60 if b & INDEXED_WITH_POST_BASE == INDEXED_WITH_POST_BASE {
61 return Representation::IndexedWithPostBase;
62 }
63
64 Representation::LiteralWithPostBase
65 }
66}
67
68#[derive(Default)]
70pub struct Decoder {}
71
72impl Decoder {
73 pub fn new() -> Decoder {
75 Decoder::default()
76 }
77
78 pub fn control(&mut self, _buf: &mut [u8]) -> Result<()> {
80 Ok(())
82 }
83
84 pub fn decode(&mut self, buf: &[u8], max_size: u64) -> Result<Vec<Header>> {
86 let mut b = octets::Octets::with_slice(buf);
87
88 let mut out = Vec::new();
89
90 let mut left = max_size;
91
92 let req_insert_count = decode_int(&mut b, 8)?;
93 let base = decode_int(&mut b, 7)?;
94
95 trace!("Header count={req_insert_count} base={base}");
96
97 while b.cap() > 0 {
98 let first = b.peek_u8()?;
99
100 match Representation::from_byte(first) {
101 Representation::Indexed => {
102 const STATIC: u8 = 0x40;
103
104 let s = first & STATIC == STATIC;
105 let index = decode_int(&mut b, 6)?;
106
107 trace!("Indexed index={index} static={s}");
108
109 if !s {
110 return Err(Error::InvalidHeaderValue);
112 }
113
114 let (name, value) = lookup_static(index)?;
115
116 left = left
117 .checked_sub((name.len() + value.len()) as u64)
118 .ok_or(Error::HeaderListTooLarge)?;
119
120 let hdr = Header::new(name, value);
121 out.push(hdr);
122 },
123
124 Representation::IndexedWithPostBase => {
125 let index = decode_int(&mut b, 4)?;
126
127 trace!("Indexed With Post Base index={index}");
128
129 return Err(Error::InvalidHeaderValue);
131 },
132
133 Representation::Literal => {
134 let name_huff = b.as_ref()[0] & 0x08 == 0x08;
135 let name_len = decode_int(&mut b, 3)? as usize;
136
137 let mut name = b.get_bytes(name_len)?;
138
139 let name = if name_huff {
140 super::huffman::decode(&mut name)?
141 } else {
142 name.to_vec()
143 };
144
145 let name = name.to_vec();
146 let value = decode_str(&mut b)?;
147
148 trace!(
149 "Literal Without Name Reference name={name:?} value={value:?}",
150 );
151
152 left = left
153 .checked_sub((name.len() + value.len()) as u64)
154 .ok_or(Error::HeaderListTooLarge)?;
155
156 let hdr = Header(name, value);
159 out.push(hdr);
160 },
161
162 Representation::LiteralWithNameRef => {
163 const STATIC: u8 = 0x10;
164
165 let s = first & STATIC == STATIC;
166 let name_idx = decode_int(&mut b, 4)?;
167 let value = decode_str(&mut b)?;
168
169 trace!(
170 "Literal name_idx={name_idx} static={s} value={value:?}"
171 );
172
173 if !s {
174 return Err(Error::InvalidHeaderValue);
176 }
177
178 let (name, _) = lookup_static(name_idx)?;
179
180 left = left
181 .checked_sub((name.len() + value.len()) as u64)
182 .ok_or(Error::HeaderListTooLarge)?;
183
184 let hdr = Header(name.to_vec(), value);
188 out.push(hdr);
189 },
190
191 Representation::LiteralWithPostBase => {
192 trace!("Literal With Post Base");
193
194 return Err(Error::InvalidHeaderValue);
196 },
197 }
198 }
199
200 Ok(out)
201 }
202}
203
204fn lookup_static(idx: u64) -> Result<(&'static [u8], &'static [u8])> {
205 if idx >= super::static_table::STATIC_DECODE_TABLE.len() as u64 {
206 return Err(Error::InvalidStaticTableIndex);
207 }
208
209 Ok(super::static_table::STATIC_DECODE_TABLE[idx as usize])
210}
211
212fn decode_int(b: &mut octets::Octets, prefix: usize) -> Result<u64> {
213 let mask = 2u64.pow(prefix as u32) - 1;
214
215 let mut val = u64::from(b.get_u8()?);
216 val &= mask;
217
218 if val < mask {
219 return Ok(val);
220 }
221
222 let mut shift = 0;
223
224 while b.cap() > 0 {
225 let byte = b.get_u8()?;
226
227 let inc = u64::from(byte & 0x7f)
228 .checked_shl(shift)
229 .ok_or(Error::BufferTooShort)?;
230
231 val = val.checked_add(inc).ok_or(Error::BufferTooShort)?;
232
233 shift += 7;
234
235 if byte & 0x80 == 0 {
236 return Ok(val);
237 }
238 }
239
240 Err(Error::BufferTooShort)
241}
242
243fn decode_str(b: &mut octets::Octets) -> Result<Vec<u8>> {
244 let first = b.peek_u8()?;
245
246 let huff = first & 0x80 == 0x80;
247
248 let len = decode_int(b, 7)? as usize;
249
250 let mut val = b.get_bytes(len)?;
251
252 let val = if huff {
253 super::huffman::decode(&mut val)?
254 } else {
255 val.to_vec()
256 };
257
258 Ok(val)
259}
260
261#[cfg(test)]
262mod tests {
263 use super::*;
264
265 #[test]
266 fn decode_int1() {
267 let encoded = [0b01010, 0x02];
268 let mut b = octets::Octets::with_slice(&encoded);
269
270 assert_eq!(decode_int(&mut b, 5), Ok(10));
271 }
272
273 #[test]
274 fn decode_int2() {
275 let encoded = [0b11111, 0b10011010, 0b00001010];
276 let mut b = octets::Octets::with_slice(&encoded);
277
278 assert_eq!(decode_int(&mut b, 5), Ok(1337));
279 }
280
281 #[test]
282 fn decode_int3() {
283 let encoded = [0b101010];
284 let mut b = octets::Octets::with_slice(&encoded);
285
286 assert_eq!(decode_int(&mut b, 8), Ok(42));
287 }
288}