Coverage Report

Created: 2025-10-28 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/h2/src/hpack/decoder.rs
Line
Count
Source
1
use super::{header::BytesStr, huffman, Header};
2
use crate::frame;
3
4
use bytes::{Buf, Bytes, BytesMut};
5
use http::header;
6
use http::method::{self, Method};
7
use http::status::{self, StatusCode};
8
9
use std::cmp;
10
use std::collections::VecDeque;
11
use std::io::Cursor;
12
use std::str::Utf8Error;
13
14
/// Decodes headers using HPACK
15
#[derive(Debug)]
16
pub struct Decoder {
17
    // Protocol indicated that the max table size will update
18
    max_size_update: Option<usize>,
19
    last_max_update: usize,
20
    table: Table,
21
    buffer: BytesMut,
22
}
23
24
/// Represents all errors that can be encountered while performing the decoding
25
/// of an HPACK header set.
26
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
27
pub enum DecoderError {
28
    InvalidRepresentation,
29
    InvalidIntegerPrefix,
30
    InvalidTableIndex,
31
    InvalidHuffmanCode,
32
    InvalidUtf8,
33
    InvalidStatusCode,
34
    InvalidPseudoheader,
35
    InvalidMaxDynamicSize,
36
    IntegerOverflow,
37
    NeedMore(NeedMore),
38
}
39
40
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
41
pub enum NeedMore {
42
    UnexpectedEndOfStream,
43
    IntegerUnderflow,
44
    StringUnderflow,
45
}
46
47
enum Representation {
48
    /// Indexed header field representation
49
    ///
50
    /// An indexed header field representation identifies an entry in either the
51
    /// static table or the dynamic table (see Section 2.3).
52
    ///
53
    /// # Header encoding
54
    ///
55
    /// ```text
56
    ///   0   1   2   3   4   5   6   7
57
    /// +---+---+---+---+---+---+---+---+
58
    /// | 1 |        Index (7+)         |
59
    /// +---+---------------------------+
60
    /// ```
61
    Indexed,
62
63
    /// Literal Header Field with Incremental Indexing
64
    ///
65
    /// A literal header field with incremental indexing representation results
66
    /// in appending a header field to the decoded header list and inserting it
67
    /// as a new entry into the dynamic table.
68
    ///
69
    /// # Header encoding
70
    ///
71
    /// ```text
72
    ///   0   1   2   3   4   5   6   7
73
    /// +---+---+---+---+---+---+---+---+
74
    /// | 0 | 1 |      Index (6+)       |
75
    /// +---+---+-----------------------+
76
    /// | H |     Value Length (7+)     |
77
    /// +---+---------------------------+
78
    /// | Value String (Length octets)  |
79
    /// +-------------------------------+
80
    /// ```
81
    LiteralWithIndexing,
82
83
    /// Literal Header Field without Indexing
84
    ///
85
    /// A literal header field without indexing representation results in
86
    /// appending a header field to the decoded header list without altering the
87
    /// dynamic table.
88
    ///
89
    /// # Header encoding
90
    ///
91
    /// ```text
92
    ///   0   1   2   3   4   5   6   7
93
    /// +---+---+---+---+---+---+---+---+
94
    /// | 0 | 0 | 0 | 0 |  Index (4+)   |
95
    /// +---+---+-----------------------+
96
    /// | H |     Value Length (7+)     |
97
    /// +---+---------------------------+
98
    /// | Value String (Length octets)  |
99
    /// +-------------------------------+
100
    /// ```
101
    LiteralWithoutIndexing,
102
103
    /// Literal Header Field Never Indexed
104
    ///
105
    /// A literal header field never-indexed representation results in appending
106
    /// a header field to the decoded header list without altering the dynamic
107
    /// table. Intermediaries MUST use the same representation for encoding this
108
    /// header field.
109
    ///
110
    /// ```text
111
    ///   0   1   2   3   4   5   6   7
112
    /// +---+---+---+---+---+---+---+---+
113
    /// | 0 | 0 | 0 | 1 |  Index (4+)   |
114
    /// +---+---+-----------------------+
115
    /// | H |     Value Length (7+)     |
116
    /// +---+---------------------------+
117
    /// | Value String (Length octets)  |
118
    /// +-------------------------------+
119
    /// ```
120
    LiteralNeverIndexed,
121
122
    /// Dynamic Table Size Update
123
    ///
124
    /// A dynamic table size update signals a change to the size of the dynamic
125
    /// table.
126
    ///
127
    /// # Header encoding
128
    ///
129
    /// ```text
130
    ///   0   1   2   3   4   5   6   7
131
    /// +---+---+---+---+---+---+---+---+
132
    /// | 0 | 0 | 1 |   Max size (5+)   |
133
    /// +---+---------------------------+
134
    /// ```
135
    SizeUpdate,
136
}
137
138
#[derive(Debug)]
139
struct Table {
140
    entries: VecDeque<Header>,
141
    size: usize,
142
    max_size: usize,
143
}
144
145
struct StringMarker {
146
    offset: usize,
147
    len: usize,
148
    string: Option<Bytes>,
149
}
150
151
// ===== impl Decoder =====
152
153
impl Decoder {
154
    /// Creates a new `Decoder` with all settings set to default values.
155
28.4k
    pub fn new(size: usize) -> Decoder {
156
28.4k
        Decoder {
157
28.4k
            max_size_update: None,
158
28.4k
            last_max_update: size,
159
28.4k
            table: Table::new(size),
160
28.4k
            buffer: BytesMut::with_capacity(4096),
161
28.4k
        }
162
28.4k
    }
163
164
    /// Queues a potential size update
165
    #[allow(dead_code)]
166
0
    pub fn queue_size_update(&mut self, size: usize) {
167
0
        let size = match self.max_size_update {
168
0
            Some(v) => cmp::max(v, size),
169
0
            None => size,
170
        };
171
172
0
        self.max_size_update = Some(size);
173
0
    }
174
175
    /// Decodes the headers found in the given buffer.
176
73.8k
    pub fn decode<F>(
177
73.8k
        &mut self,
178
73.8k
        src: &mut Cursor<&mut BytesMut>,
179
73.8k
        mut f: F,
180
73.8k
    ) -> Result<(), DecoderError>
181
73.8k
    where
182
73.8k
        F: FnMut(Header),
183
    {
184
        use self::Representation::*;
185
186
73.8k
        let mut can_resize = true;
187
188
73.8k
        if let Some(size) = self.max_size_update.take() {
189
0
            self.last_max_update = size;
190
73.8k
        }
191
192
73.8k
        let span = tracing::trace_span!("hpack::decode");
193
73.8k
        let _e = span.enter();
194
195
73.8k
        tracing::trace!("decode");
196
197
13.5M
        while let Some(ty) = peek_u8(src) {
198
            // At this point we are always at the beginning of the next block
199
            // within the HPACK data. The type of the block can always be
200
            // determined from the first byte.
201
13.4M
            match Representation::load(ty)? {
202
                Indexed => {
203
10.6M
                    tracing::trace!(rem = src.remaining(), kind = %"Indexed");
204
10.6M
                    can_resize = false;
205
10.6M
                    let entry = self.decode_indexed(src)?;
206
10.6M
                    consume(src);
207
10.6M
                    f(entry);
208
                }
209
                LiteralWithIndexing => {
210
1.30M
                    tracing::trace!(rem = src.remaining(), kind = %"LiteralWithIndexing");
211
1.30M
                    can_resize = false;
212
1.30M
                    let entry = self.decode_literal(src, true)?;
213
214
                    // Insert the header into the table
215
1.29M
                    self.table.insert(entry.clone());
216
1.29M
                    consume(src);
217
218
1.29M
                    f(entry);
219
                }
220
                LiteralWithoutIndexing => {
221
1.27M
                    tracing::trace!(rem = src.remaining(), kind = %"LiteralWithoutIndexing");
222
1.27M
                    can_resize = false;
223
1.27M
                    let entry = self.decode_literal(src, false)?;
224
1.26M
                    consume(src);
225
1.26M
                    f(entry);
226
                }
227
                LiteralNeverIndexed => {
228
274k
                    tracing::trace!(rem = src.remaining(), kind = %"LiteralNeverIndexed");
229
274k
                    can_resize = false;
230
274k
                    let entry = self.decode_literal(src, false)?;
231
271k
                    consume(src);
232
233
                    // TODO: Track that this should never be indexed
234
235
271k
                    f(entry);
236
                }
237
                SizeUpdate => {
238
10.3k
                    tracing::trace!(rem = src.remaining(), kind = %"SizeUpdate");
239
10.3k
                    if !can_resize {
240
430
                        return Err(DecoderError::InvalidMaxDynamicSize);
241
9.94k
                    }
242
243
                    // Handle the dynamic table size update
244
9.94k
                    self.process_size_update(src)?;
245
8.92k
                    consume(src);
246
                }
247
            }
248
        }
249
250
51.1k
        Ok(())
251
73.8k
    }
<h2::hpack::decoder::Decoder>::decode::<<h2::frame::headers::HeaderBlock>::load::{closure#0}>
Line
Count
Source
176
59.4k
    pub fn decode<F>(
177
59.4k
        &mut self,
178
59.4k
        src: &mut Cursor<&mut BytesMut>,
179
59.4k
        mut f: F,
180
59.4k
    ) -> Result<(), DecoderError>
181
59.4k
    where
182
59.4k
        F: FnMut(Header),
183
    {
184
        use self::Representation::*;
185
186
59.4k
        let mut can_resize = true;
187
188
59.4k
        if let Some(size) = self.max_size_update.take() {
189
0
            self.last_max_update = size;
190
59.4k
        }
191
192
59.4k
        let span = tracing::trace_span!("hpack::decode");
193
59.4k
        let _e = span.enter();
194
195
59.4k
        tracing::trace!("decode");
196
197
690k
        while let Some(ty) = peek_u8(src) {
198
            // At this point we are always at the beginning of the next block
199
            // within the HPACK data. The type of the block can always be
200
            // determined from the first byte.
201
647k
            match Representation::load(ty)? {
202
                Indexed => {
203
495k
                    tracing::trace!(rem = src.remaining(), kind = %"Indexed");
204
495k
                    can_resize = false;
205
495k
                    let entry = self.decode_indexed(src)?;
206
494k
                    consume(src);
207
494k
                    f(entry);
208
                }
209
                LiteralWithIndexing => {
210
103k
                    tracing::trace!(rem = src.remaining(), kind = %"LiteralWithIndexing");
211
103k
                    can_resize = false;
212
103k
                    let entry = self.decode_literal(src, true)?;
213
214
                    // Insert the header into the table
215
98.7k
                    self.table.insert(entry.clone());
216
98.7k
                    consume(src);
217
218
98.7k
                    f(entry);
219
                }
220
                LiteralWithoutIndexing => {
221
34.1k
                    tracing::trace!(rem = src.remaining(), kind = %"LiteralWithoutIndexing");
222
34.1k
                    can_resize = false;
223
34.1k
                    let entry = self.decode_literal(src, false)?;
224
27.8k
                    consume(src);
225
27.8k
                    f(entry);
226
                }
227
                LiteralNeverIndexed => {
228
4.38k
                    tracing::trace!(rem = src.remaining(), kind = %"LiteralNeverIndexed");
229
4.38k
                    can_resize = false;
230
4.38k
                    let entry = self.decode_literal(src, false)?;
231
1.61k
                    consume(src);
232
233
                    // TODO: Track that this should never be indexed
234
235
1.61k
                    f(entry);
236
                }
237
                SizeUpdate => {
238
9.38k
                    tracing::trace!(rem = src.remaining(), kind = %"SizeUpdate");
239
9.38k
                    if !can_resize {
240
286
                        return Err(DecoderError::InvalidMaxDynamicSize);
241
9.09k
                    }
242
243
                    // Handle the dynamic table size update
244
9.09k
                    self.process_size_update(src)?;
245
8.34k
                    consume(src);
246
                }
247
            }
248
        }
249
250
42.9k
        Ok(())
251
59.4k
    }
<h2::hpack::decoder::Decoder>::decode::<h2::fuzz_bridge::fuzz_logic::fuzz_hpack::{closure#0}>
Line
Count
Source
176
14.4k
    pub fn decode<F>(
177
14.4k
        &mut self,
178
14.4k
        src: &mut Cursor<&mut BytesMut>,
179
14.4k
        mut f: F,
180
14.4k
    ) -> Result<(), DecoderError>
181
14.4k
    where
182
14.4k
        F: FnMut(Header),
183
    {
184
        use self::Representation::*;
185
186
14.4k
        let mut can_resize = true;
187
188
14.4k
        if let Some(size) = self.max_size_update.take() {
189
0
            self.last_max_update = size;
190
14.4k
        }
191
192
14.4k
        let span = tracing::trace_span!("hpack::decode");
193
14.4k
        let _e = span.enter();
194
195
14.4k
        tracing::trace!("decode");
196
197
12.8M
        while let Some(ty) = peek_u8(src) {
198
            // At this point we are always at the beginning of the next block
199
            // within the HPACK data. The type of the block can always be
200
            // determined from the first byte.
201
12.8M
            match Representation::load(ty)? {
202
                Indexed => {
203
10.1M
                    tracing::trace!(rem = src.remaining(), kind = %"Indexed");
204
10.1M
                    can_resize = false;
205
10.1M
                    let entry = self.decode_indexed(src)?;
206
10.1M
                    consume(src);
207
10.1M
                    f(entry);
208
                }
209
                LiteralWithIndexing => {
210
1.20M
                    tracing::trace!(rem = src.remaining(), kind = %"LiteralWithIndexing");
211
1.20M
                    can_resize = false;
212
1.20M
                    let entry = self.decode_literal(src, true)?;
213
214
                    // Insert the header into the table
215
1.20M
                    self.table.insert(entry.clone());
216
1.20M
                    consume(src);
217
218
1.20M
                    f(entry);
219
                }
220
                LiteralWithoutIndexing => {
221
1.24M
                    tracing::trace!(rem = src.remaining(), kind = %"LiteralWithoutIndexing");
222
1.24M
                    can_resize = false;
223
1.24M
                    let entry = self.decode_literal(src, false)?;
224
1.23M
                    consume(src);
225
1.23M
                    f(entry);
226
                }
227
                LiteralNeverIndexed => {
228
269k
                    tracing::trace!(rem = src.remaining(), kind = %"LiteralNeverIndexed");
229
269k
                    can_resize = false;
230
269k
                    let entry = self.decode_literal(src, false)?;
231
269k
                    consume(src);
232
233
                    // TODO: Track that this should never be indexed
234
235
269k
                    f(entry);
236
                }
237
                SizeUpdate => {
238
989
                    tracing::trace!(rem = src.remaining(), kind = %"SizeUpdate");
239
989
                    if !can_resize {
240
144
                        return Err(DecoderError::InvalidMaxDynamicSize);
241
845
                    }
242
243
                    // Handle the dynamic table size update
244
845
                    self.process_size_update(src)?;
245
573
                    consume(src);
246
                }
247
            }
248
        }
249
250
8.23k
        Ok(())
251
14.4k
    }
252
253
9.94k
    fn process_size_update(&mut self, buf: &mut Cursor<&mut BytesMut>) -> Result<(), DecoderError> {
254
9.94k
        let new_size = decode_int(buf, 5)?;
255
256
9.15k
        if new_size > self.last_max_update {
257
232
            return Err(DecoderError::InvalidMaxDynamicSize);
258
8.92k
        }
259
260
8.92k
        tracing::debug!(
261
0
            from = self.table.size(),
262
            to = new_size,
263
0
            "Decoder changed max table size"
264
        );
265
266
8.92k
        self.table.set_max_size(new_size);
267
268
8.92k
        Ok(())
269
9.94k
    }
270
271
10.6M
    fn decode_indexed(&self, buf: &mut Cursor<&mut BytesMut>) -> Result<Header, DecoderError> {
272
10.6M
        let index = decode_int(buf, 7)?;
273
10.6M
        self.table.get(index)
274
10.6M
    }
275
276
2.85M
    fn decode_literal(
277
2.85M
        &mut self,
278
2.85M
        buf: &mut Cursor<&mut BytesMut>,
279
2.85M
        index: bool,
280
2.85M
    ) -> Result<Header, DecoderError> {
281
2.85M
        let prefix = if index { 6 } else { 4 };
282
283
        // Extract the table index for the name, or 0 if not indexed
284
2.85M
        let table_idx = decode_int(buf, prefix)?;
285
286
        // First, read the header name
287
2.85M
        if table_idx == 0 {
288
1.03M
            let old_pos = buf.position();
289
1.03M
            let name_marker = self.try_decode_string(buf)?;
290
1.03M
            let value_marker = self.try_decode_string(buf)?;
291
1.03M
            buf.set_position(old_pos);
292
            // Read the name as a literal
293
1.03M
            let name = name_marker.consume(buf);
294
1.03M
            let value = value_marker.consume(buf);
295
1.03M
            Header::new(name, value)
296
        } else {
297
1.81M
            let e = self.table.get(table_idx)?;
298
1.81M
            let value = self.decode_string(buf)?;
299
300
1.81M
            e.name().into_entry(value)
301
        }
302
2.85M
    }
303
304
3.88M
    fn try_decode_string(
305
3.88M
        &mut self,
306
3.88M
        buf: &mut Cursor<&mut BytesMut>,
307
3.88M
    ) -> Result<StringMarker, DecoderError> {
308
3.88M
        let old_pos = buf.position();
309
        const HUFF_FLAG: u8 = 0b1000_0000;
310
311
        // The first bit in the first byte contains the huffman encoded flag.
312
3.88M
        let huff = match peek_u8(buf) {
313
3.88M
            Some(hdr) => (hdr & HUFF_FLAG) == HUFF_FLAG,
314
3.18k
            None => return Err(DecoderError::NeedMore(NeedMore::UnexpectedEndOfStream)),
315
        };
316
317
        // Decode the string length using 7 bit prefix
318
3.88M
        let len = decode_int(buf, 7)?;
319
320
3.88M
        if len > buf.remaining() {
321
4.96k
            tracing::trace!(len, remaining = buf.remaining(), "decode_string underflow",);
322
4.96k
            return Err(DecoderError::NeedMore(NeedMore::StringUnderflow));
323
3.87M
        }
324
325
3.87M
        let offset = (buf.position() - old_pos) as usize;
326
3.87M
        if huff {
327
2.87M
            let ret = {
328
2.87M
                let raw = &buf.chunk()[..len];
329
2.87M
                huffman::decode(raw, &mut self.buffer).map(|buf| StringMarker {
330
2.87M
                    offset,
331
2.87M
                    len,
332
2.87M
                    string: Some(BytesMut::freeze(buf)),
333
2.87M
                })
334
            };
335
336
2.87M
            buf.advance(len);
337
2.87M
            ret
338
        } else {
339
1.00M
            buf.advance(len);
340
1.00M
            Ok(StringMarker {
341
1.00M
                offset,
342
1.00M
                len,
343
1.00M
                string: None,
344
1.00M
            })
345
        }
346
3.88M
    }
347
348
1.81M
    fn decode_string(&mut self, buf: &mut Cursor<&mut BytesMut>) -> Result<Bytes, DecoderError> {
349
1.81M
        let old_pos = buf.position();
350
1.81M
        let marker = self.try_decode_string(buf)?;
351
1.81M
        buf.set_position(old_pos);
352
1.81M
        Ok(marker.consume(buf))
353
1.81M
    }
354
}
355
356
impl Default for Decoder {
357
0
    fn default() -> Decoder {
358
0
        Decoder::new(4096)
359
0
    }
360
}
361
362
// ===== impl Representation =====
363
364
impl Representation {
365
13.4M
    pub fn load(byte: u8) -> Result<Representation, DecoderError> {
366
        const INDEXED: u8 = 0b1000_0000;
367
        const LITERAL_WITH_INDEXING: u8 = 0b0100_0000;
368
        const LITERAL_WITHOUT_INDEXING: u8 = 0b1111_0000;
369
        const LITERAL_NEVER_INDEXED: u8 = 0b0001_0000;
370
        const SIZE_UPDATE_MASK: u8 = 0b1110_0000;
371
        const SIZE_UPDATE: u8 = 0b0010_0000;
372
373
        // TODO: What did I even write here?
374
375
13.4M
        if byte & INDEXED == INDEXED {
376
10.6M
            Ok(Representation::Indexed)
377
2.86M
        } else if byte & LITERAL_WITH_INDEXING == LITERAL_WITH_INDEXING {
378
1.30M
            Ok(Representation::LiteralWithIndexing)
379
1.56M
        } else if byte & LITERAL_WITHOUT_INDEXING == 0 {
380
1.27M
            Ok(Representation::LiteralWithoutIndexing)
381
284k
        } else if byte & LITERAL_WITHOUT_INDEXING == LITERAL_NEVER_INDEXED {
382
274k
            Ok(Representation::LiteralNeverIndexed)
383
10.3k
        } else if byte & SIZE_UPDATE_MASK == SIZE_UPDATE {
384
10.3k
            Ok(Representation::SizeUpdate)
385
        } else {
386
0
            Err(DecoderError::InvalidRepresentation)
387
        }
388
13.4M
    }
389
}
390
391
17.3M
fn decode_int<B: Buf>(buf: &mut B, prefix_size: u8) -> Result<usize, DecoderError> {
392
    // The octet limit is chosen such that the maximum allowed *value* can
393
    // never overflow an unsigned 32-bit integer. The maximum value of any
394
    // integer that can be encoded with 5 octets is ~2^28
395
    const MAX_BYTES: usize = 5;
396
    const VARINT_MASK: u8 = 0b0111_1111;
397
    const VARINT_FLAG: u8 = 0b1000_0000;
398
399
17.3M
    if prefix_size < 1 || prefix_size > 8 {
400
0
        return Err(DecoderError::InvalidIntegerPrefix);
401
17.3M
    }
402
403
17.3M
    if !buf.has_remaining() {
404
0
        return Err(DecoderError::NeedMore(NeedMore::IntegerUnderflow));
405
17.3M
    }
406
407
17.3M
    let mask = if prefix_size == 8 {
408
0
        0xFF
409
    } else {
410
17.3M
        (1u8 << prefix_size).wrapping_sub(1)
411
    };
412
413
17.3M
    let mut ret = (buf.get_u8() & mask) as usize;
414
415
17.3M
    if ret < mask as usize {
416
        // Value fits in the prefix bits
417
17.3M
        return Ok(ret);
418
25.7k
    }
419
420
    // The int did not fit in the prefix bits, so continue reading.
421
    //
422
    // The total number of bytes used to represent the int. The first byte was
423
    // the prefix, so start at 1.
424
25.7k
    let mut bytes = 1;
425
426
    // The rest of the int is stored as a varint -- 7 bits for the value and 1
427
    // bit to indicate if it is the last byte.
428
25.7k
    let mut shift = 0;
429
430
52.3k
    while buf.has_remaining() {
431
48.6k
        let b = buf.get_u8();
432
433
48.6k
        bytes += 1;
434
48.6k
        ret += ((b & VARINT_MASK) as usize) << shift;
435
48.6k
        shift += 7;
436
437
48.6k
        if b & VARINT_FLAG == 0 {
438
21.6k
            return Ok(ret);
439
27.0k
        }
440
441
27.0k
        if bytes == MAX_BYTES {
442
            // The spec requires that this situation is an error
443
420
            return Err(DecoderError::IntegerOverflow);
444
26.5k
        }
445
    }
446
447
3.66k
    Err(DecoderError::NeedMore(NeedMore::IntegerUnderflow))
448
17.3M
}
449
450
17.4M
fn peek_u8<B: Buf>(buf: &B) -> Option<u8> {
451
17.4M
    if buf.has_remaining() {
452
17.3M
        Some(buf.chunk()[0])
453
    } else {
454
54.3k
        None
455
    }
456
17.4M
}
457
458
14.4M
fn take(buf: &mut Cursor<&mut BytesMut>, n: usize) -> Bytes {
459
14.4M
    let pos = buf.position() as usize;
460
14.4M
    let mut head = buf.get_mut().split_to(pos + n);
461
14.4M
    buf.set_position(0);
462
14.4M
    head.advance(pos);
463
14.4M
    head.freeze()
464
14.4M
}
465
466
impl StringMarker {
467
3.87M
    fn consume(self, buf: &mut Cursor<&mut BytesMut>) -> Bytes {
468
3.87M
        buf.advance(self.offset);
469
3.87M
        match self.string {
470
2.87M
            Some(string) => {
471
2.87M
                buf.advance(self.len);
472
2.87M
                string
473
            }
474
1.00M
            None => take(buf, self.len),
475
        }
476
3.87M
    }
477
}
478
479
13.4M
fn consume(buf: &mut Cursor<&mut BytesMut>) {
480
    // remove bytes from the internal BytesMut when they have been successfully
481
    // decoded. This is a more permanent cursor position, which will be
482
    // used to resume if decoding was only partial.
483
13.4M
    take(buf, 0);
484
13.4M
}
485
486
// ===== impl Table =====
487
488
impl Table {
489
28.4k
    fn new(max_size: usize) -> Table {
490
28.4k
        Table {
491
28.4k
            entries: VecDeque::new(),
492
28.4k
            size: 0,
493
28.4k
            max_size,
494
28.4k
        }
495
28.4k
    }
496
497
0
    fn size(&self) -> usize {
498
0
        self.size
499
0
    }
500
501
    /// Returns the entry located at the given index.
502
    ///
503
    /// The table is 1-indexed and constructed in such a way that the first
504
    /// entries belong to the static table, followed by entries in the dynamic
505
    /// table. They are merged into a single index address space, though.
506
    ///
507
    /// This is according to the [HPACK spec, section 2.3.3.]
508
    /// (http://http2.github.io/http2-spec/compression.html#index.address.space)
509
12.4M
    pub fn get(&self, index: usize) -> Result<Header, DecoderError> {
510
12.4M
        if index == 0 {
511
33
            return Err(DecoderError::InvalidTableIndex);
512
12.4M
        }
513
514
12.4M
        if index <= 61 {
515
12.3M
            return Ok(get_static(index));
516
70.8k
        }
517
518
        // Convert the index for lookup in the entries structure.
519
70.8k
        match self.entries.get(index - 62) {
520
70.0k
            Some(e) => Ok(e.clone()),
521
798
            None => Err(DecoderError::InvalidTableIndex),
522
        }
523
12.4M
    }
524
525
1.29M
    fn insert(&mut self, entry: Header) {
526
1.29M
        let len = entry.len();
527
528
1.29M
        self.reserve(len);
529
530
1.29M
        if self.size + len <= self.max_size {
531
91.2k
            self.size += len;
532
91.2k
533
91.2k
            // Track the entry
534
91.2k
            self.entries.push_front(entry);
535
1.20M
        }
536
1.29M
    }
537
538
8.92k
    fn set_max_size(&mut self, size: usize) {
539
8.92k
        self.max_size = size;
540
        // Make the table size fit within the new constraints.
541
8.92k
        self.consolidate();
542
8.92k
    }
543
544
1.29M
    fn reserve(&mut self, size: usize) {
545
1.32M
        while self.size + size > self.max_size {
546
1.23M
            match self.entries.pop_back() {
547
30.0k
                Some(last) => {
548
30.0k
                    self.size -= last.len();
549
30.0k
                }
550
1.20M
                None => return,
551
            }
552
        }
553
1.29M
    }
554
555
8.92k
    fn consolidate(&mut self) {
556
13.9k
        while self.size > self.max_size {
557
            {
558
5.04k
                let last = match self.entries.back() {
559
5.04k
                    Some(x) => x,
560
                    None => {
561
                        // Can never happen as the size of the table must reach
562
                        // 0 by the time we've exhausted all elements.
563
0
                        panic!("Size of table != 0, but no headers left!");
564
                    }
565
                };
566
567
5.04k
                self.size -= last.len();
568
            }
569
570
5.04k
            self.entries.pop_back();
571
        }
572
8.92k
    }
573
}
574
575
// ===== impl DecoderError =====
576
577
impl From<Utf8Error> for DecoderError {
578
50
    fn from(_: Utf8Error) -> DecoderError {
579
        // TODO: Better error?
580
50
        DecoderError::InvalidUtf8
581
50
    }
582
}
583
584
impl From<header::InvalidHeaderValue> for DecoderError {
585
324
    fn from(_: header::InvalidHeaderValue) -> DecoderError {
586
        // TODO: Better error?
587
324
        DecoderError::InvalidUtf8
588
324
    }
589
}
590
591
impl From<header::InvalidHeaderName> for DecoderError {
592
4.44k
    fn from(_: header::InvalidHeaderName) -> DecoderError {
593
        // TODO: Better error
594
4.44k
        DecoderError::InvalidUtf8
595
4.44k
    }
596
}
597
598
impl From<method::InvalidMethod> for DecoderError {
599
339
    fn from(_: method::InvalidMethod) -> DecoderError {
600
        // TODO: Better error
601
339
        DecoderError::InvalidUtf8
602
339
    }
603
}
604
605
impl From<status::InvalidStatusCode> for DecoderError {
606
8
    fn from(_: status::InvalidStatusCode) -> DecoderError {
607
        // TODO: Better error
608
8
        DecoderError::InvalidUtf8
609
8
    }
610
}
611
612
impl From<DecoderError> for frame::Error {
613
16.5k
    fn from(src: DecoderError) -> Self {
614
16.5k
        frame::Error::Hpack(src)
615
16.5k
    }
616
}
617
618
/// Get an entry from the static table
619
12.3M
pub fn get_static(idx: usize) -> Header {
620
    use http::header::HeaderValue;
621
622
12.3M
    match idx {
623
130k
        1 => Header::Authority(BytesStr::from_static("")),
624
601k
        2 => Header::Method(Method::GET),
625
1.19M
        3 => Header::Method(Method::POST),
626
1.66M
        4 => Header::Path(BytesStr::from_static("/")),
627
32.8k
        5 => Header::Path(BytesStr::from_static("/index.html")),
628
54.3k
        6 => Header::Scheme(BytesStr::from_static("http")),
629
103k
        7 => Header::Scheme(BytesStr::from_static("https")),
630
1.34M
        8 => Header::Status(StatusCode::OK),
631
251k
        9 => Header::Status(StatusCode::NO_CONTENT),
632
27.9k
        10 => Header::Status(StatusCode::PARTIAL_CONTENT),
633
38.9k
        11 => Header::Status(StatusCode::NOT_MODIFIED),
634
65.9k
        12 => Header::Status(StatusCode::BAD_REQUEST),
635
19.9k
        13 => Header::Status(StatusCode::NOT_FOUND),
636
567k
        14 => Header::Status(StatusCode::INTERNAL_SERVER_ERROR),
637
1.25M
        15 => Header::Field {
638
1.25M
            name: header::ACCEPT_CHARSET,
639
1.25M
            value: HeaderValue::from_static(""),
640
1.25M
        },
641
70.4k
        16 => Header::Field {
642
70.4k
            name: header::ACCEPT_ENCODING,
643
70.4k
            value: HeaderValue::from_static("gzip, deflate"),
644
70.4k
        },
645
128k
        17 => Header::Field {
646
128k
            name: header::ACCEPT_LANGUAGE,
647
128k
            value: HeaderValue::from_static(""),
648
128k
        },
649
140k
        18 => Header::Field {
650
140k
            name: header::ACCEPT_RANGES,
651
140k
            value: HeaderValue::from_static(""),
652
140k
        },
653
116k
        19 => Header::Field {
654
116k
            name: header::ACCEPT,
655
116k
            value: HeaderValue::from_static(""),
656
116k
        },
657
114k
        20 => Header::Field {
658
114k
            name: header::ACCESS_CONTROL_ALLOW_ORIGIN,
659
114k
            value: HeaderValue::from_static(""),
660
114k
        },
661
173k
        21 => Header::Field {
662
173k
            name: header::AGE,
663
173k
            value: HeaderValue::from_static(""),
664
173k
        },
665
23.9k
        22 => Header::Field {
666
23.9k
            name: header::ALLOW,
667
23.9k
            value: HeaderValue::from_static(""),
668
23.9k
        },
669
241k
        23 => Header::Field {
670
241k
            name: header::AUTHORIZATION,
671
241k
            value: HeaderValue::from_static(""),
672
241k
        },
673
68.3k
        24 => Header::Field {
674
68.3k
            name: header::CACHE_CONTROL,
675
68.3k
            value: HeaderValue::from_static(""),
676
68.3k
        },
677
103k
        25 => Header::Field {
678
103k
            name: header::CONTENT_DISPOSITION,
679
103k
            value: HeaderValue::from_static(""),
680
103k
        },
681
50.2k
        26 => Header::Field {
682
50.2k
            name: header::CONTENT_ENCODING,
683
50.2k
            value: HeaderValue::from_static(""),
684
50.2k
        },
685
172k
        27 => Header::Field {
686
172k
            name: header::CONTENT_LANGUAGE,
687
172k
            value: HeaderValue::from_static(""),
688
172k
        },
689
49.2k
        28 => Header::Field {
690
49.2k
            name: header::CONTENT_LENGTH,
691
49.2k
            value: HeaderValue::from_static(""),
692
49.2k
        },
693
75.0k
        29 => Header::Field {
694
75.0k
            name: header::CONTENT_LOCATION,
695
75.0k
            value: HeaderValue::from_static(""),
696
75.0k
        },
697
22.1k
        30 => Header::Field {
698
22.1k
            name: header::CONTENT_RANGE,
699
22.1k
            value: HeaderValue::from_static(""),
700
22.1k
        },
701
841k
        31 => Header::Field {
702
841k
            name: header::CONTENT_TYPE,
703
841k
            value: HeaderValue::from_static(""),
704
841k
        },
705
629k
        32 => Header::Field {
706
629k
            name: header::COOKIE,
707
629k
            value: HeaderValue::from_static(""),
708
629k
        },
709
31.0k
        33 => Header::Field {
710
31.0k
            name: header::DATE,
711
31.0k
            value: HeaderValue::from_static(""),
712
31.0k
        },
713
26.3k
        34 => Header::Field {
714
26.3k
            name: header::ETAG,
715
26.3k
            value: HeaderValue::from_static(""),
716
26.3k
        },
717
140k
        35 => Header::Field {
718
140k
            name: header::EXPECT,
719
140k
            value: HeaderValue::from_static(""),
720
140k
        },
721
102k
        36 => Header::Field {
722
102k
            name: header::EXPIRES,
723
102k
            value: HeaderValue::from_static(""),
724
102k
        },
725
34.8k
        37 => Header::Field {
726
34.8k
            name: header::FROM,
727
34.8k
            value: HeaderValue::from_static(""),
728
34.8k
        },
729
38.3k
        38 => Header::Field {
730
38.3k
            name: header::HOST,
731
38.3k
            value: HeaderValue::from_static(""),
732
38.3k
        },
733
121k
        39 => Header::Field {
734
121k
            name: header::IF_MATCH,
735
121k
            value: HeaderValue::from_static(""),
736
121k
        },
737
57.7k
        40 => Header::Field {
738
57.7k
            name: header::IF_MODIFIED_SINCE,
739
57.7k
            value: HeaderValue::from_static(""),
740
57.7k
        },
741
123k
        41 => Header::Field {
742
123k
            name: header::IF_NONE_MATCH,
743
123k
            value: HeaderValue::from_static(""),
744
123k
        },
745
24.9k
        42 => Header::Field {
746
24.9k
            name: header::IF_RANGE,
747
24.9k
            value: HeaderValue::from_static(""),
748
24.9k
        },
749
40.3k
        43 => Header::Field {
750
40.3k
            name: header::IF_UNMODIFIED_SINCE,
751
40.3k
            value: HeaderValue::from_static(""),
752
40.3k
        },
753
81.1k
        44 => Header::Field {
754
81.1k
            name: header::LAST_MODIFIED,
755
81.1k
            value: HeaderValue::from_static(""),
756
81.1k
        },
757
37.6k
        45 => Header::Field {
758
37.6k
            name: header::LINK,
759
37.6k
            value: HeaderValue::from_static(""),
760
37.6k
        },
761
207k
        46 => Header::Field {
762
207k
            name: header::LOCATION,
763
207k
            value: HeaderValue::from_static(""),
764
207k
        },
765
66.6k
        47 => Header::Field {
766
66.6k
            name: header::MAX_FORWARDS,
767
66.6k
            value: HeaderValue::from_static(""),
768
66.6k
        },
769
49.3k
        48 => Header::Field {
770
49.3k
            name: header::PROXY_AUTHENTICATE,
771
49.3k
            value: HeaderValue::from_static(""),
772
49.3k
        },
773
39.4k
        49 => Header::Field {
774
39.4k
            name: header::PROXY_AUTHORIZATION,
775
39.4k
            value: HeaderValue::from_static(""),
776
39.4k
        },
777
47.2k
        50 => Header::Field {
778
47.2k
            name: header::RANGE,
779
47.2k
            value: HeaderValue::from_static(""),
780
47.2k
        },
781
269k
        51 => Header::Field {
782
269k
            name: header::REFERER,
783
269k
            value: HeaderValue::from_static(""),
784
269k
        },
785
26.4k
        52 => Header::Field {
786
26.4k
            name: header::REFRESH,
787
26.4k
            value: HeaderValue::from_static(""),
788
26.4k
        },
789
59.5k
        53 => Header::Field {
790
59.5k
            name: header::RETRY_AFTER,
791
59.5k
            value: HeaderValue::from_static(""),
792
59.5k
        },
793
48.3k
        54 => Header::Field {
794
48.3k
            name: header::SERVER,
795
48.3k
            value: HeaderValue::from_static(""),
796
48.3k
        },
797
42.6k
        55 => Header::Field {
798
42.6k
            name: header::SET_COOKIE,
799
42.6k
            value: HeaderValue::from_static(""),
800
42.6k
        },
801
84.5k
        56 => Header::Field {
802
84.5k
            name: header::STRICT_TRANSPORT_SECURITY,
803
84.5k
            value: HeaderValue::from_static(""),
804
84.5k
        },
805
27.2k
        57 => Header::Field {
806
27.2k
            name: header::TRANSFER_ENCODING,
807
27.2k
            value: HeaderValue::from_static(""),
808
27.2k
        },
809
39.7k
        58 => Header::Field {
810
39.7k
            name: header::USER_AGENT,
811
39.7k
            value: HeaderValue::from_static(""),
812
39.7k
        },
813
35.2k
        59 => Header::Field {
814
35.2k
            name: header::VARY,
815
35.2k
            value: HeaderValue::from_static(""),
816
35.2k
        },
817
16.4k
        60 => Header::Field {
818
16.4k
            name: header::VIA,
819
16.4k
            value: HeaderValue::from_static(""),
820
16.4k
        },
821
55.9k
        61 => Header::Field {
822
55.9k
            name: header::WWW_AUTHENTICATE,
823
55.9k
            value: HeaderValue::from_static(""),
824
55.9k
        },
825
0
        _ => unreachable!(),
826
    }
827
12.3M
}
828
829
#[cfg(test)]
830
mod test {
831
    use super::*;
832
833
    #[test]
834
    fn test_peek_u8() {
835
        let b = 0xff;
836
        let mut buf = Cursor::new(vec![b]);
837
        assert_eq!(peek_u8(&buf), Some(b));
838
        assert_eq!(buf.get_u8(), b);
839
        assert_eq!(peek_u8(&buf), None);
840
    }
841
842
    #[test]
843
    fn test_decode_string_empty() {
844
        let mut de = Decoder::new(0);
845
        let mut buf = BytesMut::new();
846
        let err = de.decode_string(&mut Cursor::new(&mut buf)).unwrap_err();
847
        assert_eq!(err, DecoderError::NeedMore(NeedMore::UnexpectedEndOfStream));
848
    }
849
850
    #[test]
851
    fn test_decode_empty() {
852
        let mut de = Decoder::new(0);
853
        let mut buf = BytesMut::new();
854
        let _: () = de.decode(&mut Cursor::new(&mut buf), |_| {}).unwrap();
855
    }
856
857
    #[test]
858
    fn test_decode_indexed_larger_than_table() {
859
        let mut de = Decoder::new(0);
860
861
        let mut buf = BytesMut::new();
862
        buf.extend([0b01000000, 0x80 | 2]);
863
        buf.extend(huff_encode(b"foo"));
864
        buf.extend([0x80 | 3]);
865
        buf.extend(huff_encode(b"bar"));
866
867
        let mut res = vec![];
868
        de.decode(&mut Cursor::new(&mut buf), |h| {
869
            res.push(h);
870
        })
871
        .unwrap();
872
873
        assert_eq!(res.len(), 1);
874
        assert_eq!(de.table.size(), 0);
875
876
        match res[0] {
877
            Header::Field {
878
                ref name,
879
                ref value,
880
            } => {
881
                assert_eq!(name, "foo");
882
                assert_eq!(value, "bar");
883
            }
884
            _ => panic!(),
885
        }
886
    }
887
888
    fn huff_encode(src: &[u8]) -> BytesMut {
889
        let mut buf = BytesMut::new();
890
        huffman::encode(src, &mut buf);
891
        buf
892
    }
893
894
    #[test]
895
    fn test_decode_continuation_header_with_non_huff_encoded_name() {
896
        let mut de = Decoder::new(0);
897
        let value = huff_encode(b"bar");
898
        let mut buf = BytesMut::new();
899
        // header name is non_huff encoded
900
        buf.extend([0b01000000, 3]);
901
        buf.extend(b"foo");
902
        // header value is partial
903
        buf.extend([0x80 | 3]);
904
        buf.extend(&value[0..1]);
905
906
        let mut res = vec![];
907
        let e = de
908
            .decode(&mut Cursor::new(&mut buf), |h| {
909
                res.push(h);
910
            })
911
            .unwrap_err();
912
        // decode error because the header value is partial
913
        assert_eq!(e, DecoderError::NeedMore(NeedMore::StringUnderflow));
914
915
        // extend buf with the remaining header value
916
        buf.extend(&value[1..]);
917
        de.decode(&mut Cursor::new(&mut buf), |h| {
918
            res.push(h);
919
        })
920
        .unwrap();
921
922
        assert_eq!(res.len(), 1);
923
        assert_eq!(de.table.size(), 0);
924
925
        match res[0] {
926
            Header::Field {
927
                ref name,
928
                ref value,
929
            } => {
930
                assert_eq!(name, "foo");
931
                assert_eq!(value, "bar");
932
            }
933
            _ => panic!(),
934
        }
935
    }
936
}