h2/hpack/
decoder.rs

1use super::{header::BytesStr, huffman, Header};
2use crate::frame;
3
4use bytes::{Buf, Bytes, BytesMut};
5use http::header;
6use http::method::{self, Method};
7use http::status::{self, StatusCode};
8
9use std::cmp;
10use std::collections::VecDeque;
11use std::io::Cursor;
12use std::str::Utf8Error;
13
14/// Decodes headers using HPACK
15#[derive(Debug)]
16pub 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)]
27pub 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)]
41pub enum NeedMore {
42    UnexpectedEndOfStream,
43    IntegerUnderflow,
44    StringUnderflow,
45}
46
47enum 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)]
139struct Table {
140    entries: VecDeque<Header>,
141    size: usize,
142    max_size: usize,
143}
144
145struct StringMarker {
146    offset: usize,
147    len: usize,
148    string: Option<Bytes>,
149}
150
151// ===== impl Decoder =====
152
153impl Decoder {
154    /// Creates a new `Decoder` with all settings set to default values.
155    pub fn new(size: usize) -> Decoder {
156        Decoder {
157            max_size_update: None,
158            last_max_update: size,
159            table: Table::new(size),
160            buffer: BytesMut::with_capacity(4096),
161        }
162    }
163
164    /// Queues a potential size update
165    #[allow(dead_code)]
166    pub fn queue_size_update(&mut self, size: usize) {
167        let size = match self.max_size_update {
168            Some(v) => cmp::max(v, size),
169            None => size,
170        };
171
172        self.max_size_update = Some(size);
173    }
174
175    /// Decodes the headers found in the given buffer.
176    pub fn decode<F>(
177        &mut self,
178        src: &mut Cursor<&mut BytesMut>,
179        mut f: F,
180    ) -> Result<(), DecoderError>
181    where
182        F: FnMut(Header),
183    {
184        use self::Representation::*;
185
186        let mut can_resize = true;
187
188        if let Some(size) = self.max_size_update.take() {
189            self.last_max_update = size;
190        }
191
192        let span = tracing::trace_span!("hpack::decode");
193        let _e = span.enter();
194
195        tracing::trace!("decode");
196
197        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            match Representation::load(ty)? {
202                Indexed => {
203                    tracing::trace!(rem = src.remaining(), kind = %"Indexed");
204                    can_resize = false;
205                    let entry = self.decode_indexed(src)?;
206                    consume(src);
207                    f(entry);
208                }
209                LiteralWithIndexing => {
210                    tracing::trace!(rem = src.remaining(), kind = %"LiteralWithIndexing");
211                    can_resize = false;
212                    let entry = self.decode_literal(src, true)?;
213
214                    // Insert the header into the table
215                    self.table.insert(entry.clone());
216                    consume(src);
217
218                    f(entry);
219                }
220                LiteralWithoutIndexing => {
221                    tracing::trace!(rem = src.remaining(), kind = %"LiteralWithoutIndexing");
222                    can_resize = false;
223                    let entry = self.decode_literal(src, false)?;
224                    consume(src);
225                    f(entry);
226                }
227                LiteralNeverIndexed => {
228                    tracing::trace!(rem = src.remaining(), kind = %"LiteralNeverIndexed");
229                    can_resize = false;
230                    let entry = self.decode_literal(src, false)?;
231                    consume(src);
232
233                    // TODO: Track that this should never be indexed
234
235                    f(entry);
236                }
237                SizeUpdate => {
238                    tracing::trace!(rem = src.remaining(), kind = %"SizeUpdate");
239                    if !can_resize {
240                        return Err(DecoderError::InvalidMaxDynamicSize);
241                    }
242
243                    // Handle the dynamic table size update
244                    self.process_size_update(src)?;
245                    consume(src);
246                }
247            }
248        }
249
250        Ok(())
251    }
252
253    fn process_size_update(&mut self, buf: &mut Cursor<&mut BytesMut>) -> Result<(), DecoderError> {
254        let new_size = decode_int(buf, 5)?;
255
256        if new_size > self.last_max_update {
257            return Err(DecoderError::InvalidMaxDynamicSize);
258        }
259
260        tracing::debug!(
261            from = self.table.size(),
262            to = new_size,
263            "Decoder changed max table size"
264        );
265
266        self.table.set_max_size(new_size);
267
268        Ok(())
269    }
270
271    fn decode_indexed(&self, buf: &mut Cursor<&mut BytesMut>) -> Result<Header, DecoderError> {
272        let index = decode_int(buf, 7)?;
273        self.table.get(index)
274    }
275
276    fn decode_literal(
277        &mut self,
278        buf: &mut Cursor<&mut BytesMut>,
279        index: bool,
280    ) -> Result<Header, DecoderError> {
281        let prefix = if index { 6 } else { 4 };
282
283        // Extract the table index for the name, or 0 if not indexed
284        let table_idx = decode_int(buf, prefix)?;
285
286        // First, read the header name
287        if table_idx == 0 {
288            let old_pos = buf.position();
289            let name_marker = self.try_decode_string(buf)?;
290            let value_marker = self.try_decode_string(buf)?;
291            buf.set_position(old_pos);
292            // Read the name as a literal
293            let name = name_marker.consume(buf);
294            let value = value_marker.consume(buf);
295            Header::new(name, value)
296        } else {
297            let e = self.table.get(table_idx)?;
298            let value = self.decode_string(buf)?;
299
300            e.name().into_entry(value)
301        }
302    }
303
304    fn try_decode_string(
305        &mut self,
306        buf: &mut Cursor<&mut BytesMut>,
307    ) -> Result<StringMarker, DecoderError> {
308        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        let huff = match peek_u8(buf) {
313            Some(hdr) => (hdr & HUFF_FLAG) == HUFF_FLAG,
314            None => return Err(DecoderError::NeedMore(NeedMore::UnexpectedEndOfStream)),
315        };
316
317        // Decode the string length using 7 bit prefix
318        let len = decode_int(buf, 7)?;
319
320        if len > buf.remaining() {
321            tracing::trace!(len, remaining = buf.remaining(), "decode_string underflow",);
322            return Err(DecoderError::NeedMore(NeedMore::StringUnderflow));
323        }
324
325        let offset = (buf.position() - old_pos) as usize;
326        if huff {
327            let ret = {
328                let raw = &buf.chunk()[..len];
329                huffman::decode(raw, &mut self.buffer).map(|buf| StringMarker {
330                    offset,
331                    len,
332                    string: Some(BytesMut::freeze(buf)),
333                })
334            };
335
336            buf.advance(len);
337            ret
338        } else {
339            buf.advance(len);
340            Ok(StringMarker {
341                offset,
342                len,
343                string: None,
344            })
345        }
346    }
347
348    fn decode_string(&mut self, buf: &mut Cursor<&mut BytesMut>) -> Result<Bytes, DecoderError> {
349        let old_pos = buf.position();
350        let marker = self.try_decode_string(buf)?;
351        buf.set_position(old_pos);
352        Ok(marker.consume(buf))
353    }
354}
355
356impl Default for Decoder {
357    fn default() -> Decoder {
358        Decoder::new(4096)
359    }
360}
361
362// ===== impl Representation =====
363
364impl Representation {
365    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        if byte & INDEXED == INDEXED {
376            Ok(Representation::Indexed)
377        } else if byte & LITERAL_WITH_INDEXING == LITERAL_WITH_INDEXING {
378            Ok(Representation::LiteralWithIndexing)
379        } else if byte & LITERAL_WITHOUT_INDEXING == 0 {
380            Ok(Representation::LiteralWithoutIndexing)
381        } else if byte & LITERAL_WITHOUT_INDEXING == LITERAL_NEVER_INDEXED {
382            Ok(Representation::LiteralNeverIndexed)
383        } else if byte & SIZE_UPDATE_MASK == SIZE_UPDATE {
384            Ok(Representation::SizeUpdate)
385        } else {
386            Err(DecoderError::InvalidRepresentation)
387        }
388    }
389}
390
391fn 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    if prefix_size < 1 || prefix_size > 8 {
400        return Err(DecoderError::InvalidIntegerPrefix);
401    }
402
403    if !buf.has_remaining() {
404        return Err(DecoderError::NeedMore(NeedMore::IntegerUnderflow));
405    }
406
407    let mask = if prefix_size == 8 {
408        0xFF
409    } else {
410        (1u8 << prefix_size).wrapping_sub(1)
411    };
412
413    let mut ret = (buf.get_u8() & mask) as usize;
414
415    if ret < mask as usize {
416        // Value fits in the prefix bits
417        return Ok(ret);
418    }
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    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    let mut shift = 0;
429
430    while buf.has_remaining() {
431        let b = buf.get_u8();
432
433        bytes += 1;
434        ret += ((b & VARINT_MASK) as usize) << shift;
435        shift += 7;
436
437        if b & VARINT_FLAG == 0 {
438            return Ok(ret);
439        }
440
441        if bytes == MAX_BYTES {
442            // The spec requires that this situation is an error
443            return Err(DecoderError::IntegerOverflow);
444        }
445    }
446
447    Err(DecoderError::NeedMore(NeedMore::IntegerUnderflow))
448}
449
450fn peek_u8<B: Buf>(buf: &B) -> Option<u8> {
451    if buf.has_remaining() {
452        Some(buf.chunk()[0])
453    } else {
454        None
455    }
456}
457
458fn take(buf: &mut Cursor<&mut BytesMut>, n: usize) -> Bytes {
459    let pos = buf.position() as usize;
460    let mut head = buf.get_mut().split_to(pos + n);
461    buf.set_position(0);
462    head.advance(pos);
463    head.freeze()
464}
465
466impl StringMarker {
467    fn consume(self, buf: &mut Cursor<&mut BytesMut>) -> Bytes {
468        buf.advance(self.offset);
469        match self.string {
470            Some(string) => {
471                buf.advance(self.len);
472                string
473            }
474            None => take(buf, self.len),
475        }
476    }
477}
478
479fn 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    take(buf, 0);
484}
485
486// ===== impl Table =====
487
488impl Table {
489    fn new(max_size: usize) -> Table {
490        Table {
491            entries: VecDeque::new(),
492            size: 0,
493            max_size,
494        }
495    }
496
497    fn size(&self) -> usize {
498        self.size
499    }
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    pub fn get(&self, index: usize) -> Result<Header, DecoderError> {
510        if index == 0 {
511            return Err(DecoderError::InvalidTableIndex);
512        }
513
514        if index <= 61 {
515            return Ok(get_static(index));
516        }
517
518        // Convert the index for lookup in the entries structure.
519        match self.entries.get(index - 62) {
520            Some(e) => Ok(e.clone()),
521            None => Err(DecoderError::InvalidTableIndex),
522        }
523    }
524
525    fn insert(&mut self, entry: Header) {
526        let len = entry.len();
527
528        self.reserve(len);
529
530        if self.size + len <= self.max_size {
531            self.size += len;
532
533            // Track the entry
534            self.entries.push_front(entry);
535        }
536    }
537
538    fn set_max_size(&mut self, size: usize) {
539        self.max_size = size;
540        // Make the table size fit within the new constraints.
541        self.consolidate();
542    }
543
544    fn reserve(&mut self, size: usize) {
545        while self.size + size > self.max_size {
546            match self.entries.pop_back() {
547                Some(last) => {
548                    self.size -= last.len();
549                }
550                None => return,
551            }
552        }
553    }
554
555    fn consolidate(&mut self) {
556        while self.size > self.max_size {
557            {
558                let last = match self.entries.back() {
559                    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                        panic!("Size of table != 0, but no headers left!");
564                    }
565                };
566
567                self.size -= last.len();
568            }
569
570            self.entries.pop_back();
571        }
572    }
573}
574
575// ===== impl DecoderError =====
576
577impl From<Utf8Error> for DecoderError {
578    fn from(_: Utf8Error) -> DecoderError {
579        // TODO: Better error?
580        DecoderError::InvalidUtf8
581    }
582}
583
584impl From<header::InvalidHeaderValue> for DecoderError {
585    fn from(_: header::InvalidHeaderValue) -> DecoderError {
586        // TODO: Better error?
587        DecoderError::InvalidUtf8
588    }
589}
590
591impl From<header::InvalidHeaderName> for DecoderError {
592    fn from(_: header::InvalidHeaderName) -> DecoderError {
593        // TODO: Better error
594        DecoderError::InvalidUtf8
595    }
596}
597
598impl From<method::InvalidMethod> for DecoderError {
599    fn from(_: method::InvalidMethod) -> DecoderError {
600        // TODO: Better error
601        DecoderError::InvalidUtf8
602    }
603}
604
605impl From<status::InvalidStatusCode> for DecoderError {
606    fn from(_: status::InvalidStatusCode) -> DecoderError {
607        // TODO: Better error
608        DecoderError::InvalidUtf8
609    }
610}
611
612impl From<DecoderError> for frame::Error {
613    fn from(src: DecoderError) -> Self {
614        frame::Error::Hpack(src)
615    }
616}
617
618/// Get an entry from the static table
619pub fn get_static(idx: usize) -> Header {
620    use http::header::HeaderValue;
621
622    match idx {
623        1 => Header::Authority(BytesStr::from_static("")),
624        2 => Header::Method(Method::GET),
625        3 => Header::Method(Method::POST),
626        4 => Header::Path(BytesStr::from_static("/")),
627        5 => Header::Path(BytesStr::from_static("/index.html")),
628        6 => Header::Scheme(BytesStr::from_static("http")),
629        7 => Header::Scheme(BytesStr::from_static("https")),
630        8 => Header::Status(StatusCode::OK),
631        9 => Header::Status(StatusCode::NO_CONTENT),
632        10 => Header::Status(StatusCode::PARTIAL_CONTENT),
633        11 => Header::Status(StatusCode::NOT_MODIFIED),
634        12 => Header::Status(StatusCode::BAD_REQUEST),
635        13 => Header::Status(StatusCode::NOT_FOUND),
636        14 => Header::Status(StatusCode::INTERNAL_SERVER_ERROR),
637        15 => Header::Field {
638            name: header::ACCEPT_CHARSET,
639            value: HeaderValue::from_static(""),
640        },
641        16 => Header::Field {
642            name: header::ACCEPT_ENCODING,
643            value: HeaderValue::from_static("gzip, deflate"),
644        },
645        17 => Header::Field {
646            name: header::ACCEPT_LANGUAGE,
647            value: HeaderValue::from_static(""),
648        },
649        18 => Header::Field {
650            name: header::ACCEPT_RANGES,
651            value: HeaderValue::from_static(""),
652        },
653        19 => Header::Field {
654            name: header::ACCEPT,
655            value: HeaderValue::from_static(""),
656        },
657        20 => Header::Field {
658            name: header::ACCESS_CONTROL_ALLOW_ORIGIN,
659            value: HeaderValue::from_static(""),
660        },
661        21 => Header::Field {
662            name: header::AGE,
663            value: HeaderValue::from_static(""),
664        },
665        22 => Header::Field {
666            name: header::ALLOW,
667            value: HeaderValue::from_static(""),
668        },
669        23 => Header::Field {
670            name: header::AUTHORIZATION,
671            value: HeaderValue::from_static(""),
672        },
673        24 => Header::Field {
674            name: header::CACHE_CONTROL,
675            value: HeaderValue::from_static(""),
676        },
677        25 => Header::Field {
678            name: header::CONTENT_DISPOSITION,
679            value: HeaderValue::from_static(""),
680        },
681        26 => Header::Field {
682            name: header::CONTENT_ENCODING,
683            value: HeaderValue::from_static(""),
684        },
685        27 => Header::Field {
686            name: header::CONTENT_LANGUAGE,
687            value: HeaderValue::from_static(""),
688        },
689        28 => Header::Field {
690            name: header::CONTENT_LENGTH,
691            value: HeaderValue::from_static(""),
692        },
693        29 => Header::Field {
694            name: header::CONTENT_LOCATION,
695            value: HeaderValue::from_static(""),
696        },
697        30 => Header::Field {
698            name: header::CONTENT_RANGE,
699            value: HeaderValue::from_static(""),
700        },
701        31 => Header::Field {
702            name: header::CONTENT_TYPE,
703            value: HeaderValue::from_static(""),
704        },
705        32 => Header::Field {
706            name: header::COOKIE,
707            value: HeaderValue::from_static(""),
708        },
709        33 => Header::Field {
710            name: header::DATE,
711            value: HeaderValue::from_static(""),
712        },
713        34 => Header::Field {
714            name: header::ETAG,
715            value: HeaderValue::from_static(""),
716        },
717        35 => Header::Field {
718            name: header::EXPECT,
719            value: HeaderValue::from_static(""),
720        },
721        36 => Header::Field {
722            name: header::EXPIRES,
723            value: HeaderValue::from_static(""),
724        },
725        37 => Header::Field {
726            name: header::FROM,
727            value: HeaderValue::from_static(""),
728        },
729        38 => Header::Field {
730            name: header::HOST,
731            value: HeaderValue::from_static(""),
732        },
733        39 => Header::Field {
734            name: header::IF_MATCH,
735            value: HeaderValue::from_static(""),
736        },
737        40 => Header::Field {
738            name: header::IF_MODIFIED_SINCE,
739            value: HeaderValue::from_static(""),
740        },
741        41 => Header::Field {
742            name: header::IF_NONE_MATCH,
743            value: HeaderValue::from_static(""),
744        },
745        42 => Header::Field {
746            name: header::IF_RANGE,
747            value: HeaderValue::from_static(""),
748        },
749        43 => Header::Field {
750            name: header::IF_UNMODIFIED_SINCE,
751            value: HeaderValue::from_static(""),
752        },
753        44 => Header::Field {
754            name: header::LAST_MODIFIED,
755            value: HeaderValue::from_static(""),
756        },
757        45 => Header::Field {
758            name: header::LINK,
759            value: HeaderValue::from_static(""),
760        },
761        46 => Header::Field {
762            name: header::LOCATION,
763            value: HeaderValue::from_static(""),
764        },
765        47 => Header::Field {
766            name: header::MAX_FORWARDS,
767            value: HeaderValue::from_static(""),
768        },
769        48 => Header::Field {
770            name: header::PROXY_AUTHENTICATE,
771            value: HeaderValue::from_static(""),
772        },
773        49 => Header::Field {
774            name: header::PROXY_AUTHORIZATION,
775            value: HeaderValue::from_static(""),
776        },
777        50 => Header::Field {
778            name: header::RANGE,
779            value: HeaderValue::from_static(""),
780        },
781        51 => Header::Field {
782            name: header::REFERER,
783            value: HeaderValue::from_static(""),
784        },
785        52 => Header::Field {
786            name: header::REFRESH,
787            value: HeaderValue::from_static(""),
788        },
789        53 => Header::Field {
790            name: header::RETRY_AFTER,
791            value: HeaderValue::from_static(""),
792        },
793        54 => Header::Field {
794            name: header::SERVER,
795            value: HeaderValue::from_static(""),
796        },
797        55 => Header::Field {
798            name: header::SET_COOKIE,
799            value: HeaderValue::from_static(""),
800        },
801        56 => Header::Field {
802            name: header::STRICT_TRANSPORT_SECURITY,
803            value: HeaderValue::from_static(""),
804        },
805        57 => Header::Field {
806            name: header::TRANSFER_ENCODING,
807            value: HeaderValue::from_static(""),
808        },
809        58 => Header::Field {
810            name: header::USER_AGENT,
811            value: HeaderValue::from_static(""),
812        },
813        59 => Header::Field {
814            name: header::VARY,
815            value: HeaderValue::from_static(""),
816        },
817        60 => Header::Field {
818            name: header::VIA,
819            value: HeaderValue::from_static(""),
820        },
821        61 => Header::Field {
822            name: header::WWW_AUTHENTICATE,
823            value: HeaderValue::from_static(""),
824        },
825        _ => unreachable!(),
826    }
827}
828
829#[cfg(test)]
830mod 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}