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 // ===== impl Decoder =====
146
147 impl Decoder {
148 /// Creates a new `Decoder` with all settings set to default values.
new(size: usize) -> Decoder149 pub fn new(size: usize) -> Decoder {
150 Decoder {
151 max_size_update: None,
152 last_max_update: size,
153 table: Table::new(size),
154 buffer: BytesMut::with_capacity(4096),
155 }
156 }
157
158 /// Queues a potential size update
159 #[allow(dead_code)]
queue_size_update(&mut self, size: usize)160 pub fn queue_size_update(&mut self, size: usize) {
161 let size = match self.max_size_update {
162 Some(v) => cmp::max(v, size),
163 None => size,
164 };
165
166 self.max_size_update = Some(size);
167 }
168
169 /// Decodes the headers found in the given buffer.
decode<F>( &mut self, src: &mut Cursor<&mut BytesMut>, mut f: F, ) -> Result<(), DecoderError> where F: FnMut(Header),170 pub fn decode<F>(
171 &mut self,
172 src: &mut Cursor<&mut BytesMut>,
173 mut f: F,
174 ) -> Result<(), DecoderError>
175 where
176 F: FnMut(Header),
177 {
178 use self::Representation::*;
179
180 let mut can_resize = true;
181
182 if let Some(size) = self.max_size_update.take() {
183 self.last_max_update = size;
184 }
185
186 tracing::trace!("decode");
187
188 while let Some(ty) = peek_u8(src) {
189 // At this point we are always at the beginning of the next block
190 // within the HPACK data. The type of the block can always be
191 // determined from the first byte.
192 match Representation::load(ty)? {
193 Indexed => {
194 tracing::trace!(" Indexed; rem={:?}", src.remaining());
195 can_resize = false;
196 let entry = self.decode_indexed(src)?;
197 consume(src);
198 f(entry);
199 }
200 LiteralWithIndexing => {
201 tracing::trace!(" LiteralWithIndexing; rem={:?}", src.remaining());
202 can_resize = false;
203 let entry = self.decode_literal(src, true)?;
204
205 // Insert the header into the table
206 self.table.insert(entry.clone());
207 consume(src);
208
209 f(entry);
210 }
211 LiteralWithoutIndexing => {
212 tracing::trace!(" LiteralWithoutIndexing; rem={:?}", src.remaining());
213 can_resize = false;
214 let entry = self.decode_literal(src, false)?;
215 consume(src);
216 f(entry);
217 }
218 LiteralNeverIndexed => {
219 tracing::trace!(" LiteralNeverIndexed; rem={:?}", src.remaining());
220 can_resize = false;
221 let entry = self.decode_literal(src, false)?;
222 consume(src);
223
224 // TODO: Track that this should never be indexed
225
226 f(entry);
227 }
228 SizeUpdate => {
229 tracing::trace!(" SizeUpdate; rem={:?}", src.remaining());
230 if !can_resize {
231 return Err(DecoderError::InvalidMaxDynamicSize);
232 }
233
234 // Handle the dynamic table size update
235 self.process_size_update(src)?;
236 consume(src);
237 }
238 }
239 }
240
241 Ok(())
242 }
243
process_size_update(&mut self, buf: &mut Cursor<&mut BytesMut>) -> Result<(), DecoderError>244 fn process_size_update(&mut self, buf: &mut Cursor<&mut BytesMut>) -> Result<(), DecoderError> {
245 let new_size = decode_int(buf, 5)?;
246
247 if new_size > self.last_max_update {
248 return Err(DecoderError::InvalidMaxDynamicSize);
249 }
250
251 tracing::debug!(
252 "Decoder changed max table size from {} to {}",
253 self.table.size(),
254 new_size
255 );
256
257 self.table.set_max_size(new_size);
258
259 Ok(())
260 }
261
decode_indexed(&self, buf: &mut Cursor<&mut BytesMut>) -> Result<Header, DecoderError>262 fn decode_indexed(&self, buf: &mut Cursor<&mut BytesMut>) -> Result<Header, DecoderError> {
263 let index = decode_int(buf, 7)?;
264 self.table.get(index)
265 }
266
decode_literal( &mut self, buf: &mut Cursor<&mut BytesMut>, index: bool, ) -> Result<Header, DecoderError>267 fn decode_literal(
268 &mut self,
269 buf: &mut Cursor<&mut BytesMut>,
270 index: bool,
271 ) -> Result<Header, DecoderError> {
272 let prefix = if index { 6 } else { 4 };
273
274 // Extract the table index for the name, or 0 if not indexed
275 let table_idx = decode_int(buf, prefix)?;
276
277 // First, read the header name
278 if table_idx == 0 {
279 // Read the name as a literal
280 let name = self.decode_string(buf)?;
281 let value = self.decode_string(buf)?;
282
283 Header::new(name, value)
284 } else {
285 let e = self.table.get(table_idx)?;
286 let value = self.decode_string(buf)?;
287
288 e.name().into_entry(value)
289 }
290 }
291
decode_string(&mut self, buf: &mut Cursor<&mut BytesMut>) -> Result<Bytes, DecoderError>292 fn decode_string(&mut self, buf: &mut Cursor<&mut BytesMut>) -> Result<Bytes, DecoderError> {
293 const HUFF_FLAG: u8 = 0b1000_0000;
294
295 // The first bit in the first byte contains the huffman encoded flag.
296 let huff = match peek_u8(buf) {
297 Some(hdr) => (hdr & HUFF_FLAG) == HUFF_FLAG,
298 None => return Err(DecoderError::NeedMore(NeedMore::UnexpectedEndOfStream)),
299 };
300
301 // Decode the string length using 7 bit prefix
302 let len = decode_int(buf, 7)?;
303
304 if len > buf.remaining() {
305 tracing::trace!(
306 "decode_string underflow; len={}; remaining={}",
307 len,
308 buf.remaining()
309 );
310 return Err(DecoderError::NeedMore(NeedMore::StringUnderflow));
311 }
312
313 if huff {
314 let ret = {
315 let raw = &buf.bytes()[..len];
316 huffman::decode(raw, &mut self.buffer).map(BytesMut::freeze)
317 };
318
319 buf.advance(len);
320 return ret;
321 }
322
323 Ok(take(buf, len))
324 }
325 }
326
327 impl Default for Decoder {
default() -> Decoder328 fn default() -> Decoder {
329 Decoder::new(4096)
330 }
331 }
332
333 // ===== impl Representation =====
334
335 impl Representation {
load(byte: u8) -> Result<Representation, DecoderError>336 pub fn load(byte: u8) -> Result<Representation, DecoderError> {
337 const INDEXED: u8 = 0b1000_0000;
338 const LITERAL_WITH_INDEXING: u8 = 0b0100_0000;
339 const LITERAL_WITHOUT_INDEXING: u8 = 0b1111_0000;
340 const LITERAL_NEVER_INDEXED: u8 = 0b0001_0000;
341 const SIZE_UPDATE_MASK: u8 = 0b1110_0000;
342 const SIZE_UPDATE: u8 = 0b0010_0000;
343
344 // TODO: What did I even write here?
345
346 if byte & INDEXED == INDEXED {
347 Ok(Representation::Indexed)
348 } else if byte & LITERAL_WITH_INDEXING == LITERAL_WITH_INDEXING {
349 Ok(Representation::LiteralWithIndexing)
350 } else if byte & LITERAL_WITHOUT_INDEXING == 0 {
351 Ok(Representation::LiteralWithoutIndexing)
352 } else if byte & LITERAL_WITHOUT_INDEXING == LITERAL_NEVER_INDEXED {
353 Ok(Representation::LiteralNeverIndexed)
354 } else if byte & SIZE_UPDATE_MASK == SIZE_UPDATE {
355 Ok(Representation::SizeUpdate)
356 } else {
357 Err(DecoderError::InvalidRepresentation)
358 }
359 }
360 }
361
decode_int<B: Buf>(buf: &mut B, prefix_size: u8) -> Result<usize, DecoderError>362 fn decode_int<B: Buf>(buf: &mut B, prefix_size: u8) -> Result<usize, DecoderError> {
363 // The octet limit is chosen such that the maximum allowed *value* can
364 // never overflow an unsigned 32-bit integer. The maximum value of any
365 // integer that can be encoded with 5 octets is ~2^28
366 const MAX_BYTES: usize = 5;
367 const VARINT_MASK: u8 = 0b0111_1111;
368 const VARINT_FLAG: u8 = 0b1000_0000;
369
370 if prefix_size < 1 || prefix_size > 8 {
371 return Err(DecoderError::InvalidIntegerPrefix);
372 }
373
374 if !buf.has_remaining() {
375 return Err(DecoderError::NeedMore(NeedMore::IntegerUnderflow));
376 }
377
378 let mask = if prefix_size == 8 {
379 0xFF
380 } else {
381 (1u8 << prefix_size).wrapping_sub(1)
382 };
383
384 let mut ret = (buf.get_u8() & mask) as usize;
385
386 if ret < mask as usize {
387 // Value fits in the prefix bits
388 return Ok(ret);
389 }
390
391 // The int did not fit in the prefix bits, so continue reading.
392 //
393 // The total number of bytes used to represent the int. The first byte was
394 // the prefix, so start at 1.
395 let mut bytes = 1;
396
397 // The rest of the int is stored as a varint -- 7 bits for the value and 1
398 // bit to indicate if it is the last byte.
399 let mut shift = 0;
400
401 while buf.has_remaining() {
402 let b = buf.get_u8();
403
404 bytes += 1;
405 ret += ((b & VARINT_MASK) as usize) << shift;
406 shift += 7;
407
408 if b & VARINT_FLAG == 0 {
409 return Ok(ret);
410 }
411
412 if bytes == MAX_BYTES {
413 // The spec requires that this situation is an error
414 return Err(DecoderError::IntegerOverflow);
415 }
416 }
417
418 Err(DecoderError::NeedMore(NeedMore::IntegerUnderflow))
419 }
420
peek_u8<B: Buf>(buf: &mut B) -> Option<u8>421 fn peek_u8<B: Buf>(buf: &mut B) -> Option<u8> {
422 if buf.has_remaining() {
423 Some(buf.bytes()[0])
424 } else {
425 None
426 }
427 }
428
take(buf: &mut Cursor<&mut BytesMut>, n: usize) -> Bytes429 fn take(buf: &mut Cursor<&mut BytesMut>, n: usize) -> Bytes {
430 let pos = buf.position() as usize;
431 let mut head = buf.get_mut().split_to(pos + n);
432 buf.set_position(0);
433 head.advance(pos);
434 head.freeze()
435 }
436
consume(buf: &mut Cursor<&mut BytesMut>)437 fn consume(buf: &mut Cursor<&mut BytesMut>) {
438 // remove bytes from the internal BytesMut when they have been successfully
439 // decoded. This is a more permanent cursor position, which will be
440 // used to resume if decoding was only partial.
441 take(buf, 0);
442 }
443
444 // ===== impl Table =====
445
446 impl Table {
new(max_size: usize) -> Table447 fn new(max_size: usize) -> Table {
448 Table {
449 entries: VecDeque::new(),
450 size: 0,
451 max_size,
452 }
453 }
454
size(&self) -> usize455 fn size(&self) -> usize {
456 self.size
457 }
458
459 /// Returns the entry located at the given index.
460 ///
461 /// The table is 1-indexed and constructed in such a way that the first
462 /// entries belong to the static table, followed by entries in the dynamic
463 /// table. They are merged into a single index address space, though.
464 ///
465 /// This is according to the [HPACK spec, section 2.3.3.]
466 /// (http://http2.github.io/http2-spec/compression.html#index.address.space)
get(&self, index: usize) -> Result<Header, DecoderError>467 pub fn get(&self, index: usize) -> Result<Header, DecoderError> {
468 if index == 0 {
469 return Err(DecoderError::InvalidTableIndex);
470 }
471
472 if index <= 61 {
473 return Ok(get_static(index));
474 }
475
476 // Convert the index for lookup in the entries structure.
477 match self.entries.get(index - 62) {
478 Some(e) => Ok(e.clone()),
479 None => Err(DecoderError::InvalidTableIndex),
480 }
481 }
482
insert(&mut self, entry: Header)483 fn insert(&mut self, entry: Header) {
484 let len = entry.len();
485
486 self.reserve(len);
487
488 if self.size + len <= self.max_size {
489 self.size += len;
490
491 // Track the entry
492 self.entries.push_front(entry);
493 }
494 }
495
set_max_size(&mut self, size: usize)496 fn set_max_size(&mut self, size: usize) {
497 self.max_size = size;
498 // Make the table size fit within the new constraints.
499 self.consolidate();
500 }
501
reserve(&mut self, size: usize)502 fn reserve(&mut self, size: usize) {
503 while self.size + size > self.max_size {
504 match self.entries.pop_back() {
505 Some(last) => {
506 self.size -= last.len();
507 }
508 None => return,
509 }
510 }
511 }
512
consolidate(&mut self)513 fn consolidate(&mut self) {
514 while self.size > self.max_size {
515 {
516 let last = match self.entries.back() {
517 Some(x) => x,
518 None => {
519 // Can never happen as the size of the table must reach
520 // 0 by the time we've exhausted all elements.
521 panic!("Size of table != 0, but no headers left!");
522 }
523 };
524
525 self.size -= last.len();
526 }
527
528 self.entries.pop_back();
529 }
530 }
531 }
532
533 // ===== impl DecoderError =====
534
535 impl From<Utf8Error> for DecoderError {
from(_: Utf8Error) -> DecoderError536 fn from(_: Utf8Error) -> DecoderError {
537 // TODO: Better error?
538 DecoderError::InvalidUtf8
539 }
540 }
541
542 impl From<header::InvalidHeaderValue> for DecoderError {
from(_: header::InvalidHeaderValue) -> DecoderError543 fn from(_: header::InvalidHeaderValue) -> DecoderError {
544 // TODO: Better error?
545 DecoderError::InvalidUtf8
546 }
547 }
548
549 impl From<header::InvalidHeaderName> for DecoderError {
from(_: header::InvalidHeaderName) -> DecoderError550 fn from(_: header::InvalidHeaderName) -> DecoderError {
551 // TODO: Better error
552 DecoderError::InvalidUtf8
553 }
554 }
555
556 impl From<method::InvalidMethod> for DecoderError {
from(_: method::InvalidMethod) -> DecoderError557 fn from(_: method::InvalidMethod) -> DecoderError {
558 // TODO: Better error
559 DecoderError::InvalidUtf8
560 }
561 }
562
563 impl From<status::InvalidStatusCode> for DecoderError {
from(_: status::InvalidStatusCode) -> DecoderError564 fn from(_: status::InvalidStatusCode) -> DecoderError {
565 // TODO: Better error
566 DecoderError::InvalidUtf8
567 }
568 }
569
570 impl From<DecoderError> for frame::Error {
from(src: DecoderError) -> Self571 fn from(src: DecoderError) -> Self {
572 frame::Error::Hpack(src)
573 }
574 }
575
576 /// Get an entry from the static table
get_static(idx: usize) -> Header577 pub fn get_static(idx: usize) -> Header {
578 use http::header::HeaderValue;
579
580 match idx {
581 1 => Header::Authority(from_static("")),
582 2 => Header::Method(Method::GET),
583 3 => Header::Method(Method::POST),
584 4 => Header::Path(from_static("/")),
585 5 => Header::Path(from_static("/index.html")),
586 6 => Header::Scheme(from_static("http")),
587 7 => Header::Scheme(from_static("https")),
588 8 => Header::Status(StatusCode::OK),
589 9 => Header::Status(StatusCode::NO_CONTENT),
590 10 => Header::Status(StatusCode::PARTIAL_CONTENT),
591 11 => Header::Status(StatusCode::NOT_MODIFIED),
592 12 => Header::Status(StatusCode::BAD_REQUEST),
593 13 => Header::Status(StatusCode::NOT_FOUND),
594 14 => Header::Status(StatusCode::INTERNAL_SERVER_ERROR),
595 15 => Header::Field {
596 name: header::ACCEPT_CHARSET,
597 value: HeaderValue::from_static(""),
598 },
599 16 => Header::Field {
600 name: header::ACCEPT_ENCODING,
601 value: HeaderValue::from_static("gzip, deflate"),
602 },
603 17 => Header::Field {
604 name: header::ACCEPT_LANGUAGE,
605 value: HeaderValue::from_static(""),
606 },
607 18 => Header::Field {
608 name: header::ACCEPT_RANGES,
609 value: HeaderValue::from_static(""),
610 },
611 19 => Header::Field {
612 name: header::ACCEPT,
613 value: HeaderValue::from_static(""),
614 },
615 20 => Header::Field {
616 name: header::ACCESS_CONTROL_ALLOW_ORIGIN,
617 value: HeaderValue::from_static(""),
618 },
619 21 => Header::Field {
620 name: header::AGE,
621 value: HeaderValue::from_static(""),
622 },
623 22 => Header::Field {
624 name: header::ALLOW,
625 value: HeaderValue::from_static(""),
626 },
627 23 => Header::Field {
628 name: header::AUTHORIZATION,
629 value: HeaderValue::from_static(""),
630 },
631 24 => Header::Field {
632 name: header::CACHE_CONTROL,
633 value: HeaderValue::from_static(""),
634 },
635 25 => Header::Field {
636 name: header::CONTENT_DISPOSITION,
637 value: HeaderValue::from_static(""),
638 },
639 26 => Header::Field {
640 name: header::CONTENT_ENCODING,
641 value: HeaderValue::from_static(""),
642 },
643 27 => Header::Field {
644 name: header::CONTENT_LANGUAGE,
645 value: HeaderValue::from_static(""),
646 },
647 28 => Header::Field {
648 name: header::CONTENT_LENGTH,
649 value: HeaderValue::from_static(""),
650 },
651 29 => Header::Field {
652 name: header::CONTENT_LOCATION,
653 value: HeaderValue::from_static(""),
654 },
655 30 => Header::Field {
656 name: header::CONTENT_RANGE,
657 value: HeaderValue::from_static(""),
658 },
659 31 => Header::Field {
660 name: header::CONTENT_TYPE,
661 value: HeaderValue::from_static(""),
662 },
663 32 => Header::Field {
664 name: header::COOKIE,
665 value: HeaderValue::from_static(""),
666 },
667 33 => Header::Field {
668 name: header::DATE,
669 value: HeaderValue::from_static(""),
670 },
671 34 => Header::Field {
672 name: header::ETAG,
673 value: HeaderValue::from_static(""),
674 },
675 35 => Header::Field {
676 name: header::EXPECT,
677 value: HeaderValue::from_static(""),
678 },
679 36 => Header::Field {
680 name: header::EXPIRES,
681 value: HeaderValue::from_static(""),
682 },
683 37 => Header::Field {
684 name: header::FROM,
685 value: HeaderValue::from_static(""),
686 },
687 38 => Header::Field {
688 name: header::HOST,
689 value: HeaderValue::from_static(""),
690 },
691 39 => Header::Field {
692 name: header::IF_MATCH,
693 value: HeaderValue::from_static(""),
694 },
695 40 => Header::Field {
696 name: header::IF_MODIFIED_SINCE,
697 value: HeaderValue::from_static(""),
698 },
699 41 => Header::Field {
700 name: header::IF_NONE_MATCH,
701 value: HeaderValue::from_static(""),
702 },
703 42 => Header::Field {
704 name: header::IF_RANGE,
705 value: HeaderValue::from_static(""),
706 },
707 43 => Header::Field {
708 name: header::IF_UNMODIFIED_SINCE,
709 value: HeaderValue::from_static(""),
710 },
711 44 => Header::Field {
712 name: header::LAST_MODIFIED,
713 value: HeaderValue::from_static(""),
714 },
715 45 => Header::Field {
716 name: header::LINK,
717 value: HeaderValue::from_static(""),
718 },
719 46 => Header::Field {
720 name: header::LOCATION,
721 value: HeaderValue::from_static(""),
722 },
723 47 => Header::Field {
724 name: header::MAX_FORWARDS,
725 value: HeaderValue::from_static(""),
726 },
727 48 => Header::Field {
728 name: header::PROXY_AUTHENTICATE,
729 value: HeaderValue::from_static(""),
730 },
731 49 => Header::Field {
732 name: header::PROXY_AUTHORIZATION,
733 value: HeaderValue::from_static(""),
734 },
735 50 => Header::Field {
736 name: header::RANGE,
737 value: HeaderValue::from_static(""),
738 },
739 51 => Header::Field {
740 name: header::REFERER,
741 value: HeaderValue::from_static(""),
742 },
743 52 => Header::Field {
744 name: header::REFRESH,
745 value: HeaderValue::from_static(""),
746 },
747 53 => Header::Field {
748 name: header::RETRY_AFTER,
749 value: HeaderValue::from_static(""),
750 },
751 54 => Header::Field {
752 name: header::SERVER,
753 value: HeaderValue::from_static(""),
754 },
755 55 => Header::Field {
756 name: header::SET_COOKIE,
757 value: HeaderValue::from_static(""),
758 },
759 56 => Header::Field {
760 name: header::STRICT_TRANSPORT_SECURITY,
761 value: HeaderValue::from_static(""),
762 },
763 57 => Header::Field {
764 name: header::TRANSFER_ENCODING,
765 value: HeaderValue::from_static(""),
766 },
767 58 => Header::Field {
768 name: header::USER_AGENT,
769 value: HeaderValue::from_static(""),
770 },
771 59 => Header::Field {
772 name: header::VARY,
773 value: HeaderValue::from_static(""),
774 },
775 60 => Header::Field {
776 name: header::VIA,
777 value: HeaderValue::from_static(""),
778 },
779 61 => Header::Field {
780 name: header::WWW_AUTHENTICATE,
781 value: HeaderValue::from_static(""),
782 },
783 _ => unreachable!(),
784 }
785 }
786
from_static(s: &'static str) -> BytesStr787 fn from_static(s: &'static str) -> BytesStr {
788 unsafe { BytesStr::from_utf8_unchecked(Bytes::from_static(s.as_bytes())) }
789 }
790
791 #[cfg(test)]
792 mod test {
793 use super::*;
794 use crate::hpack::Header;
795
796 #[test]
test_peek_u8()797 fn test_peek_u8() {
798 let b = 0xff;
799 let mut buf = Cursor::new(vec![b]);
800 assert_eq!(peek_u8(&mut buf), Some(b));
801 assert_eq!(buf.get_u8(), b);
802 assert_eq!(peek_u8(&mut buf), None);
803 }
804
805 #[test]
test_decode_string_empty()806 fn test_decode_string_empty() {
807 let mut de = Decoder::new(0);
808 let mut buf = BytesMut::new();
809 let err = de.decode_string(&mut Cursor::new(&mut buf)).unwrap_err();
810 assert_eq!(err, DecoderError::NeedMore(NeedMore::UnexpectedEndOfStream));
811 }
812
813 #[test]
test_decode_empty()814 fn test_decode_empty() {
815 let mut de = Decoder::new(0);
816 let mut buf = BytesMut::new();
817 let empty = de.decode(&mut Cursor::new(&mut buf), |_| {}).unwrap();
818 assert_eq!(empty, ());
819 }
820
821 #[test]
test_decode_indexed_larger_than_table()822 fn test_decode_indexed_larger_than_table() {
823 let mut de = Decoder::new(0);
824
825 let mut buf = BytesMut::new();
826 buf.extend(&[0b01000000, 0x80 | 2]);
827 buf.extend(huff_encode(b"foo"));
828 buf.extend(&[0x80 | 3]);
829 buf.extend(huff_encode(b"bar"));
830
831 let mut res = vec![];
832 let _ = de
833 .decode(&mut Cursor::new(&mut buf), |h| {
834 res.push(h);
835 })
836 .unwrap();
837
838 assert_eq!(res.len(), 1);
839 assert_eq!(de.table.size(), 0);
840
841 match res[0] {
842 Header::Field {
843 ref name,
844 ref value,
845 } => {
846 assert_eq!(name, "foo");
847 assert_eq!(value, "bar");
848 }
849 _ => panic!(),
850 }
851 }
852
huff_encode(src: &[u8]) -> BytesMut853 fn huff_encode(src: &[u8]) -> BytesMut {
854 let mut buf = BytesMut::new();
855 huffman::encode(src, &mut buf).unwrap();
856 buf
857 }
858 }
859