1 use super::table::{Index, Table};
2 use super::{huffman, Header};
3 
4 use bytes::{buf::ext::Limit, BufMut, BytesMut};
5 use http::header::{HeaderName, HeaderValue};
6 
7 type DstBuf<'a> = Limit<&'a mut BytesMut>;
8 
9 #[derive(Debug)]
10 pub struct Encoder {
11     table: Table,
12     size_update: Option<SizeUpdate>,
13 }
14 
15 #[derive(Debug)]
16 pub enum Encode {
17     Full,
18     Partial(EncodeState),
19 }
20 
21 #[derive(Debug)]
22 pub struct EncodeState {
23     index: Index,
24     value: Option<HeaderValue>,
25 }
26 
27 #[derive(Debug, PartialEq, Eq)]
28 pub enum EncoderError {
29     BufferOverflow,
30 }
31 
32 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
33 enum SizeUpdate {
34     One(usize),
35     Two(usize, usize), // min, max
36 }
37 
38 impl Encoder {
new(max_size: usize, capacity: usize) -> Encoder39     pub fn new(max_size: usize, capacity: usize) -> Encoder {
40         Encoder {
41             table: Table::new(max_size, capacity),
42             size_update: None,
43         }
44     }
45 
46     /// Queues a max size update.
47     ///
48     /// The next call to `encode` will include a dynamic size update frame.
update_max_size(&mut self, val: usize)49     pub fn update_max_size(&mut self, val: usize) {
50         match self.size_update {
51             Some(SizeUpdate::One(old)) => {
52                 if val > old {
53                     if old > self.table.max_size() {
54                         self.size_update = Some(SizeUpdate::One(val));
55                     } else {
56                         self.size_update = Some(SizeUpdate::Two(old, val));
57                     }
58                 } else {
59                     self.size_update = Some(SizeUpdate::One(val));
60                 }
61             }
62             Some(SizeUpdate::Two(min, _)) => {
63                 if val < min {
64                     self.size_update = Some(SizeUpdate::One(val));
65                 } else {
66                     self.size_update = Some(SizeUpdate::Two(min, val));
67                 }
68             }
69             None => {
70                 if val != self.table.max_size() {
71                     // Don't bother writing a frame if the value already matches
72                     // the table's max size.
73                     self.size_update = Some(SizeUpdate::One(val));
74                 }
75             }
76         }
77     }
78 
79     /// Encode a set of headers into the provide buffer
encode<I>( &mut self, resume: Option<EncodeState>, headers: &mut I, dst: &mut DstBuf<'_>, ) -> Encode where I: Iterator<Item = Header<Option<HeaderName>>>,80     pub fn encode<I>(
81         &mut self,
82         resume: Option<EncodeState>,
83         headers: &mut I,
84         dst: &mut DstBuf<'_>,
85     ) -> Encode
86     where
87         I: Iterator<Item = Header<Option<HeaderName>>>,
88     {
89         let pos = position(dst);
90 
91         if let Err(e) = self.encode_size_updates(dst) {
92             if e == EncoderError::BufferOverflow {
93                 rewind(dst, pos);
94             }
95 
96             unreachable!("encode_size_updates errored");
97         }
98 
99         let mut last_index = None;
100 
101         if let Some(resume) = resume {
102             let pos = position(dst);
103 
104             let res = match resume.value {
105                 Some(ref value) => self.encode_header_without_name(&resume.index, value, dst),
106                 None => self.encode_header(&resume.index, dst),
107             };
108 
109             if res.is_err() {
110                 rewind(dst, pos);
111                 return Encode::Partial(resume);
112             }
113             last_index = Some(resume.index);
114         }
115 
116         for header in headers {
117             let pos = position(dst);
118 
119             match header.reify() {
120                 // The header has an associated name. In which case, try to
121                 // index it in the table.
122                 Ok(header) => {
123                     let index = self.table.index(header);
124                     let res = self.encode_header(&index, dst);
125 
126                     if res.is_err() {
127                         rewind(dst, pos);
128                         return Encode::Partial(EncodeState { index, value: None });
129                     }
130 
131                     last_index = Some(index);
132                 }
133                 // The header does not have an associated name. This means that
134                 // the name is the same as the previously yielded header. In
135                 // which case, we skip table lookup and just use the same index
136                 // as the previous entry.
137                 Err(value) => {
138                     let res = self.encode_header_without_name(
139                         last_index.as_ref().unwrap_or_else(|| {
140                             panic!("encoding header without name, but no previous index to use for name");
141                         }),
142                         &value,
143                         dst,
144                     );
145 
146                     if res.is_err() {
147                         rewind(dst, pos);
148                         return Encode::Partial(EncodeState {
149                             index: last_index.unwrap(), // checked just above
150                             value: Some(value),
151                         });
152                     }
153                 }
154             };
155         }
156 
157         Encode::Full
158     }
159 
encode_size_updates(&mut self, dst: &mut DstBuf<'_>) -> Result<(), EncoderError>160     fn encode_size_updates(&mut self, dst: &mut DstBuf<'_>) -> Result<(), EncoderError> {
161         match self.size_update.take() {
162             Some(SizeUpdate::One(val)) => {
163                 self.table.resize(val);
164                 encode_size_update(val, dst)?;
165             }
166             Some(SizeUpdate::Two(min, max)) => {
167                 self.table.resize(min);
168                 self.table.resize(max);
169                 encode_size_update(min, dst)?;
170                 encode_size_update(max, dst)?;
171             }
172             None => {}
173         }
174 
175         Ok(())
176     }
177 
encode_header(&mut self, index: &Index, dst: &mut DstBuf<'_>) -> Result<(), EncoderError>178     fn encode_header(&mut self, index: &Index, dst: &mut DstBuf<'_>) -> Result<(), EncoderError> {
179         match *index {
180             Index::Indexed(idx, _) => {
181                 encode_int(idx, 7, 0x80, dst)?;
182             }
183             Index::Name(idx, _) => {
184                 let header = self.table.resolve(&index);
185 
186                 encode_not_indexed(idx, header.value_slice(), header.is_sensitive(), dst)?;
187             }
188             Index::Inserted(_) => {
189                 let header = self.table.resolve(&index);
190 
191                 assert!(!header.is_sensitive());
192 
193                 if !dst.has_remaining_mut() {
194                     return Err(EncoderError::BufferOverflow);
195                 }
196 
197                 dst.put_u8(0b0100_0000);
198 
199                 encode_str(header.name().as_slice(), dst)?;
200                 encode_str(header.value_slice(), dst)?;
201             }
202             Index::InsertedValue(idx, _) => {
203                 let header = self.table.resolve(&index);
204 
205                 assert!(!header.is_sensitive());
206 
207                 encode_int(idx, 6, 0b0100_0000, dst)?;
208                 encode_str(header.value_slice(), dst)?;
209             }
210             Index::NotIndexed(_) => {
211                 let header = self.table.resolve(&index);
212 
213                 encode_not_indexed2(
214                     header.name().as_slice(),
215                     header.value_slice(),
216                     header.is_sensitive(),
217                     dst,
218                 )?;
219             }
220         }
221 
222         Ok(())
223     }
224 
encode_header_without_name( &mut self, last: &Index, value: &HeaderValue, dst: &mut DstBuf<'_>, ) -> Result<(), EncoderError>225     fn encode_header_without_name(
226         &mut self,
227         last: &Index,
228         value: &HeaderValue,
229         dst: &mut DstBuf<'_>,
230     ) -> Result<(), EncoderError> {
231         match *last {
232             Index::Indexed(..)
233             | Index::Name(..)
234             | Index::Inserted(..)
235             | Index::InsertedValue(..) => {
236                 let idx = self.table.resolve_idx(last);
237 
238                 encode_not_indexed(idx, value.as_ref(), value.is_sensitive(), dst)?;
239             }
240             Index::NotIndexed(_) => {
241                 let last = self.table.resolve(last);
242 
243                 encode_not_indexed2(
244                     last.name().as_slice(),
245                     value.as_ref(),
246                     value.is_sensitive(),
247                     dst,
248                 )?;
249             }
250         }
251 
252         Ok(())
253     }
254 }
255 
256 impl Default for Encoder {
default() -> Encoder257     fn default() -> Encoder {
258         Encoder::new(4096, 0)
259     }
260 }
261 
encode_size_update<B: BufMut>(val: usize, dst: &mut B) -> Result<(), EncoderError>262 fn encode_size_update<B: BufMut>(val: usize, dst: &mut B) -> Result<(), EncoderError> {
263     encode_int(val, 5, 0b0010_0000, dst)
264 }
265 
encode_not_indexed( name: usize, value: &[u8], sensitive: bool, dst: &mut DstBuf<'_>, ) -> Result<(), EncoderError>266 fn encode_not_indexed(
267     name: usize,
268     value: &[u8],
269     sensitive: bool,
270     dst: &mut DstBuf<'_>,
271 ) -> Result<(), EncoderError> {
272     if sensitive {
273         encode_int(name, 4, 0b10000, dst)?;
274     } else {
275         encode_int(name, 4, 0, dst)?;
276     }
277 
278     encode_str(value, dst)?;
279     Ok(())
280 }
281 
encode_not_indexed2( name: &[u8], value: &[u8], sensitive: bool, dst: &mut DstBuf<'_>, ) -> Result<(), EncoderError>282 fn encode_not_indexed2(
283     name: &[u8],
284     value: &[u8],
285     sensitive: bool,
286     dst: &mut DstBuf<'_>,
287 ) -> Result<(), EncoderError> {
288     if !dst.has_remaining_mut() {
289         return Err(EncoderError::BufferOverflow);
290     }
291 
292     if sensitive {
293         dst.put_u8(0b10000);
294     } else {
295         dst.put_u8(0);
296     }
297 
298     encode_str(name, dst)?;
299     encode_str(value, dst)?;
300     Ok(())
301 }
302 
encode_str(val: &[u8], dst: &mut DstBuf<'_>) -> Result<(), EncoderError>303 fn encode_str(val: &[u8], dst: &mut DstBuf<'_>) -> Result<(), EncoderError> {
304     if !dst.has_remaining_mut() {
305         return Err(EncoderError::BufferOverflow);
306     }
307 
308     if !val.is_empty() {
309         let idx = position(dst);
310 
311         // Push a placeholder byte for the length header
312         dst.put_u8(0);
313 
314         // Encode with huffman
315         huffman::encode(val, dst)?;
316 
317         let huff_len = position(dst) - (idx + 1);
318 
319         if encode_int_one_byte(huff_len, 7) {
320             // Write the string head
321             dst.get_mut()[idx] = 0x80 | huff_len as u8;
322         } else {
323             // Write the head to a placeholer
324             const PLACEHOLDER_LEN: usize = 8;
325             let mut buf = [0u8; PLACEHOLDER_LEN];
326 
327             let head_len = {
328                 let mut head_dst = &mut buf[..];
329                 encode_int(huff_len, 7, 0x80, &mut head_dst)?;
330                 PLACEHOLDER_LEN - head_dst.remaining_mut()
331             };
332 
333             if dst.remaining_mut() < head_len {
334                 return Err(EncoderError::BufferOverflow);
335             }
336 
337             // This is just done to reserve space in the destination
338             dst.put_slice(&buf[1..head_len]);
339 
340             let written = dst.get_mut();
341             // Shift the header forward
342             for i in 0..huff_len {
343                 let src_i = idx + 1 + (huff_len - (i + 1));
344                 let dst_i = idx + head_len + (huff_len - (i + 1));
345                 written[dst_i] = written[src_i];
346             }
347 
348             // Copy in the head
349             for i in 0..head_len {
350                 written[idx + i] = buf[i];
351             }
352         }
353     } else {
354         // Write an empty string
355         dst.put_u8(0);
356     }
357 
358     Ok(())
359 }
360 
361 /// Encode an integer into the given destination buffer
encode_int<B: BufMut>( mut value: usize, prefix_bits: usize, first_byte: u8, dst: &mut B, ) -> Result<(), EncoderError>362 fn encode_int<B: BufMut>(
363     mut value: usize,   // The integer to encode
364     prefix_bits: usize, // The number of bits in the prefix
365     first_byte: u8,     // The base upon which to start encoding the int
366     dst: &mut B,
367 ) -> Result<(), EncoderError> {
368     let mut rem = dst.remaining_mut();
369 
370     if rem == 0 {
371         return Err(EncoderError::BufferOverflow);
372     }
373 
374     if encode_int_one_byte(value, prefix_bits) {
375         dst.put_u8(first_byte | value as u8);
376         return Ok(());
377     }
378 
379     let low = (1 << prefix_bits) - 1;
380 
381     value -= low;
382 
383     if value > 0x0fff_ffff {
384         panic!("value out of range");
385     }
386 
387     dst.put_u8(first_byte | low as u8);
388     rem -= 1;
389 
390     while value >= 128 {
391         if rem == 0 {
392             return Err(EncoderError::BufferOverflow);
393         }
394 
395         dst.put_u8(0b1000_0000 | value as u8);
396         rem -= 1;
397 
398         value >>= 7;
399     }
400 
401     if rem == 0 {
402         return Err(EncoderError::BufferOverflow);
403     }
404 
405     dst.put_u8(value as u8);
406 
407     Ok(())
408 }
409 
410 /// Returns true if the in the int can be fully encoded in the first byte.
encode_int_one_byte(value: usize, prefix_bits: usize) -> bool411 fn encode_int_one_byte(value: usize, prefix_bits: usize) -> bool {
412     value < (1 << prefix_bits) - 1
413 }
414 
position(buf: &DstBuf<'_>) -> usize415 fn position(buf: &DstBuf<'_>) -> usize {
416     buf.get_ref().len()
417 }
418 
rewind(buf: &mut DstBuf<'_>, pos: usize)419 fn rewind(buf: &mut DstBuf<'_>, pos: usize) {
420     buf.get_mut().truncate(pos);
421 }
422 
423 #[cfg(test)]
424 mod test {
425     use super::*;
426     use crate::hpack::Header;
427     use bytes::buf::BufMutExt;
428     use http::*;
429 
430     #[test]
test_encode_method_get()431     fn test_encode_method_get() {
432         let mut encoder = Encoder::default();
433         let res = encode(&mut encoder, vec![method("GET")]);
434         assert_eq!(*res, [0x80 | 2]);
435         assert_eq!(encoder.table.len(), 0);
436     }
437 
438     #[test]
test_encode_method_post()439     fn test_encode_method_post() {
440         let mut encoder = Encoder::default();
441         let res = encode(&mut encoder, vec![method("POST")]);
442         assert_eq!(*res, [0x80 | 3]);
443         assert_eq!(encoder.table.len(), 0);
444     }
445 
446     #[test]
test_encode_method_patch()447     fn test_encode_method_patch() {
448         let mut encoder = Encoder::default();
449         let res = encode(&mut encoder, vec![method("PATCH")]);
450 
451         assert_eq!(res[0], 0b01000000 | 2); // Incremental indexing w/ name pulled from table
452         assert_eq!(res[1], 0x80 | 5); // header value w/ huffman coding
453 
454         assert_eq!("PATCH", huff_decode(&res[2..7]));
455         assert_eq!(encoder.table.len(), 1);
456 
457         let res = encode(&mut encoder, vec![method("PATCH")]);
458 
459         assert_eq!(1 << 7 | 62, res[0]);
460         assert_eq!(1, res.len());
461     }
462 
463     #[test]
test_encode_indexed_name_literal_value()464     fn test_encode_indexed_name_literal_value() {
465         let mut encoder = Encoder::default();
466         let res = encode(&mut encoder, vec![header("content-language", "foo")]);
467 
468         assert_eq!(res[0], 0b01000000 | 27); // Indexed name
469         assert_eq!(res[1], 0x80 | 2); // header value w/ huffman coding
470 
471         assert_eq!("foo", huff_decode(&res[2..4]));
472 
473         // Same name, new value should still use incremental
474         let res = encode(&mut encoder, vec![header("content-language", "bar")]);
475         assert_eq!(res[0], 0b01000000 | 27); // Indexed name
476         assert_eq!(res[1], 0x80 | 3); // header value w/ huffman coding
477         assert_eq!("bar", huff_decode(&res[2..5]));
478     }
479 
480     #[test]
test_repeated_headers_are_indexed()481     fn test_repeated_headers_are_indexed() {
482         let mut encoder = Encoder::default();
483         let res = encode(&mut encoder, vec![header("foo", "hello")]);
484 
485         assert_eq!(&[0b01000000, 0x80 | 2], &res[0..2]);
486         assert_eq!("foo", huff_decode(&res[2..4]));
487         assert_eq!(0x80 | 4, res[4]);
488         assert_eq!("hello", huff_decode(&res[5..]));
489         assert_eq!(9, res.len());
490 
491         assert_eq!(1, encoder.table.len());
492 
493         let res = encode(&mut encoder, vec![header("foo", "hello")]);
494         assert_eq!([0x80 | 62], *res);
495 
496         assert_eq!(encoder.table.len(), 1);
497     }
498 
499     #[test]
test_evicting_headers()500     fn test_evicting_headers() {
501         let mut encoder = Encoder::default();
502 
503         // Fill the table
504         for i in 0..64 {
505             let key = format!("x-hello-world-{:02}", i);
506             let res = encode(&mut encoder, vec![header(&key, &key)]);
507 
508             assert_eq!(&[0b01000000, 0x80 | 12], &res[0..2]);
509             assert_eq!(key, huff_decode(&res[2..14]));
510             assert_eq!(0x80 | 12, res[14]);
511             assert_eq!(key, huff_decode(&res[15..]));
512             assert_eq!(27, res.len());
513 
514             // Make sure the header can be found...
515             let res = encode(&mut encoder, vec![header(&key, &key)]);
516 
517             // Only check that it is found
518             assert_eq!(0x80, res[0] & 0x80);
519         }
520 
521         assert_eq!(4096, encoder.table.size());
522         assert_eq!(64, encoder.table.len());
523 
524         // Find existing headers
525         for i in 0..64 {
526             let key = format!("x-hello-world-{:02}", i);
527             let res = encode(&mut encoder, vec![header(&key, &key)]);
528             assert_eq!(0x80, res[0] & 0x80);
529         }
530 
531         // Insert a new header
532         let key = "x-hello-world-64";
533         let res = encode(&mut encoder, vec![header(key, key)]);
534 
535         assert_eq!(&[0b01000000, 0x80 | 12], &res[0..2]);
536         assert_eq!(key, huff_decode(&res[2..14]));
537         assert_eq!(0x80 | 12, res[14]);
538         assert_eq!(key, huff_decode(&res[15..]));
539         assert_eq!(27, res.len());
540 
541         assert_eq!(64, encoder.table.len());
542 
543         // Now try encoding entries that should exist in the table
544         for i in 1..65 {
545             let key = format!("x-hello-world-{:02}", i);
546             let res = encode(&mut encoder, vec![header(&key, &key)]);
547             assert_eq!(0x80 | (61 + (65 - i)), res[0]);
548         }
549     }
550 
551     #[test]
test_large_headers_are_not_indexed()552     fn test_large_headers_are_not_indexed() {
553         let mut encoder = Encoder::new(128, 0);
554         let key = "hello-world-hello-world-HELLO-zzz";
555 
556         let res = encode(&mut encoder, vec![header(key, key)]);
557 
558         assert_eq!(&[0, 0x80 | 25], &res[..2]);
559 
560         assert_eq!(0, encoder.table.len());
561         assert_eq!(0, encoder.table.size());
562     }
563 
564     #[test]
test_sensitive_headers_are_never_indexed()565     fn test_sensitive_headers_are_never_indexed() {
566         use http::header::HeaderValue;
567 
568         let name = "my-password".parse().unwrap();
569         let mut value = HeaderValue::from_bytes(b"12345").unwrap();
570         value.set_sensitive(true);
571 
572         let header = Header::Field {
573             name: Some(name),
574             value,
575         };
576 
577         // Now, try to encode the sensitive header
578 
579         let mut encoder = Encoder::default();
580         let res = encode(&mut encoder, vec![header]);
581 
582         assert_eq!(&[0b10000, 0x80 | 8], &res[..2]);
583         assert_eq!("my-password", huff_decode(&res[2..10]));
584         assert_eq!(0x80 | 4, res[10]);
585         assert_eq!("12345", huff_decode(&res[11..]));
586 
587         // Now, try to encode a sensitive header w/ a name in the static table
588         let name = "authorization".parse().unwrap();
589         let mut value = HeaderValue::from_bytes(b"12345").unwrap();
590         value.set_sensitive(true);
591 
592         let header = Header::Field {
593             name: Some(name),
594             value,
595         };
596 
597         let mut encoder = Encoder::default();
598         let res = encode(&mut encoder, vec![header]);
599 
600         assert_eq!(&[0b11111, 8], &res[..2]);
601         assert_eq!(0x80 | 4, res[2]);
602         assert_eq!("12345", huff_decode(&res[3..]));
603 
604         // Using the name component of a previously indexed header (without
605         // sensitive flag set)
606 
607         let _ = encode(
608             &mut encoder,
609             vec![self::header("my-password", "not-so-secret")],
610         );
611 
612         let name = "my-password".parse().unwrap();
613         let mut value = HeaderValue::from_bytes(b"12345").unwrap();
614         value.set_sensitive(true);
615 
616         let header = Header::Field {
617             name: Some(name),
618             value,
619         };
620         let res = encode(&mut encoder, vec![header]);
621 
622         assert_eq!(&[0b11111, 47], &res[..2]);
623         assert_eq!(0x80 | 4, res[2]);
624         assert_eq!("12345", huff_decode(&res[3..]));
625     }
626 
627     #[test]
test_content_length_value_not_indexed()628     fn test_content_length_value_not_indexed() {
629         let mut encoder = Encoder::default();
630         let res = encode(&mut encoder, vec![header("content-length", "1234")]);
631 
632         assert_eq!(&[15, 13, 0x80 | 3], &res[0..3]);
633         assert_eq!("1234", huff_decode(&res[3..]));
634         assert_eq!(6, res.len());
635     }
636 
637     #[test]
test_encoding_headers_with_same_name()638     fn test_encoding_headers_with_same_name() {
639         let mut encoder = Encoder::default();
640         let name = "hello";
641 
642         // Encode first one
643         let _ = encode(&mut encoder, vec![header(name, "one")]);
644 
645         // Encode second one
646         let res = encode(&mut encoder, vec![header(name, "two")]);
647         assert_eq!(&[0x40 | 62, 0x80 | 3], &res[0..2]);
648         assert_eq!("two", huff_decode(&res[2..]));
649         assert_eq!(5, res.len());
650 
651         // Encode the first one again
652         let res = encode(&mut encoder, vec![header(name, "one")]);
653         assert_eq!(&[0x80 | 63], &res[..]);
654 
655         // Now the second one
656         let res = encode(&mut encoder, vec![header(name, "two")]);
657         assert_eq!(&[0x80 | 62], &res[..]);
658     }
659 
660     #[test]
test_evicting_headers_when_multiple_of_same_name_are_in_table()661     fn test_evicting_headers_when_multiple_of_same_name_are_in_table() {
662         // The encoder only has space for 2 headers
663         let mut encoder = Encoder::new(76, 0);
664 
665         let _ = encode(&mut encoder, vec![header("foo", "bar")]);
666         assert_eq!(1, encoder.table.len());
667 
668         let _ = encode(&mut encoder, vec![header("bar", "foo")]);
669         assert_eq!(2, encoder.table.len());
670 
671         // This will evict the first header, while still referencing the header
672         // name
673         let res = encode(&mut encoder, vec![header("foo", "baz")]);
674         assert_eq!(&[0x40 | 63, 0, 0x80 | 3], &res[..3]);
675         assert_eq!(2, encoder.table.len());
676 
677         // Try adding the same header again
678         let res = encode(&mut encoder, vec![header("foo", "baz")]);
679         assert_eq!(&[0x80 | 62], &res[..]);
680         assert_eq!(2, encoder.table.len());
681     }
682 
683     #[test]
test_max_size_zero()684     fn test_max_size_zero() {
685         // Static table only
686         let mut encoder = Encoder::new(0, 0);
687         let res = encode(&mut encoder, vec![method("GET")]);
688         assert_eq!(*res, [0x80 | 2]);
689         assert_eq!(encoder.table.len(), 0);
690 
691         let res = encode(&mut encoder, vec![header("foo", "bar")]);
692         assert_eq!(&[0, 0x80 | 2], &res[..2]);
693         assert_eq!("foo", huff_decode(&res[2..4]));
694         assert_eq!(0x80 | 3, res[4]);
695         assert_eq!("bar", huff_decode(&res[5..8]));
696         assert_eq!(0, encoder.table.len());
697 
698         // Encode a custom value
699         let res = encode(&mut encoder, vec![header("transfer-encoding", "chunked")]);
700         assert_eq!(&[15, 42, 0x80 | 6], &res[..3]);
701         assert_eq!("chunked", huff_decode(&res[3..]));
702     }
703 
704     #[test]
test_update_max_size_combos()705     fn test_update_max_size_combos() {
706         let mut encoder = Encoder::default();
707         assert!(encoder.size_update.is_none());
708         assert_eq!(4096, encoder.table.max_size());
709 
710         encoder.update_max_size(4096); // Default size
711         assert!(encoder.size_update.is_none());
712 
713         encoder.update_max_size(0);
714         assert_eq!(Some(SizeUpdate::One(0)), encoder.size_update);
715 
716         encoder.update_max_size(100);
717         assert_eq!(Some(SizeUpdate::Two(0, 100)), encoder.size_update);
718 
719         let mut encoder = Encoder::default();
720         encoder.update_max_size(8000);
721         assert_eq!(Some(SizeUpdate::One(8000)), encoder.size_update);
722 
723         encoder.update_max_size(100);
724         assert_eq!(Some(SizeUpdate::One(100)), encoder.size_update);
725 
726         encoder.update_max_size(8000);
727         assert_eq!(Some(SizeUpdate::Two(100, 8000)), encoder.size_update);
728 
729         encoder.update_max_size(4000);
730         assert_eq!(Some(SizeUpdate::Two(100, 4000)), encoder.size_update);
731 
732         encoder.update_max_size(50);
733         assert_eq!(Some(SizeUpdate::One(50)), encoder.size_update);
734     }
735 
736     #[test]
test_resizing_table()737     fn test_resizing_table() {
738         let mut encoder = Encoder::default();
739 
740         // Add a header
741         let _ = encode(&mut encoder, vec![header("foo", "bar")]);
742 
743         encoder.update_max_size(1);
744         assert_eq!(1, encoder.table.len());
745 
746         let res = encode(&mut encoder, vec![method("GET")]);
747         assert_eq!(&[32 | 1, 0x80 | 2], &res[..]);
748         assert_eq!(0, encoder.table.len());
749 
750         let res = encode(&mut encoder, vec![header("foo", "bar")]);
751         assert_eq!(0, res[0]);
752 
753         encoder.update_max_size(100);
754         let res = encode(&mut encoder, vec![header("foo", "bar")]);
755         assert_eq!(&[32 | 31, 69, 64], &res[..3]);
756 
757         encoder.update_max_size(0);
758         let res = encode(&mut encoder, vec![header("foo", "bar")]);
759         assert_eq!(&[32, 0], &res[..2]);
760     }
761 
762     #[test]
test_decreasing_table_size_without_eviction()763     fn test_decreasing_table_size_without_eviction() {
764         let mut encoder = Encoder::default();
765 
766         // Add a header
767         let _ = encode(&mut encoder, vec![header("foo", "bar")]);
768 
769         encoder.update_max_size(100);
770         assert_eq!(1, encoder.table.len());
771 
772         let res = encode(&mut encoder, vec![header("foo", "bar")]);
773         assert_eq!(&[32 | 31, 69, 0x80 | 62], &res[..]);
774     }
775 
776     #[test]
test_nameless_header()777     fn test_nameless_header() {
778         let mut encoder = Encoder::default();
779 
780         let res = encode(
781             &mut encoder,
782             vec![
783                 Header::Field {
784                     name: Some("hello".parse().unwrap()),
785                     value: HeaderValue::from_bytes(b"world").unwrap(),
786                 },
787                 Header::Field {
788                     name: None,
789                     value: HeaderValue::from_bytes(b"zomg").unwrap(),
790                 },
791             ],
792         );
793 
794         assert_eq!(&[0x40, 0x80 | 4], &res[0..2]);
795         assert_eq!("hello", huff_decode(&res[2..6]));
796         assert_eq!(0x80 | 4, res[6]);
797         assert_eq!("world", huff_decode(&res[7..11]));
798 
799         // Next is not indexed
800         assert_eq!(&[15, 47, 0x80 | 3], &res[11..14]);
801         assert_eq!("zomg", huff_decode(&res[14..]));
802     }
803 
804     #[test]
test_nameless_header_at_resume()805     fn test_nameless_header_at_resume() {
806         let mut encoder = Encoder::default();
807         let max_len = 15;
808         let mut dst = BytesMut::with_capacity(64);
809 
810         let mut input = vec![
811             Header::Field {
812                 name: Some("hello".parse().unwrap()),
813                 value: HeaderValue::from_bytes(b"world").unwrap(),
814             },
815             Header::Field {
816                 name: None,
817                 value: HeaderValue::from_bytes(b"zomg").unwrap(),
818             },
819             Header::Field {
820                 name: None,
821                 value: HeaderValue::from_bytes(b"sup").unwrap(),
822             },
823         ]
824         .into_iter();
825 
826         let resume = match encoder.encode(None, &mut input, &mut (&mut dst).limit(max_len)) {
827             Encode::Partial(r) => r,
828             _ => panic!("encode should be partial"),
829         };
830 
831         assert_eq!(&[0x40, 0x80 | 4], &dst[0..2]);
832         assert_eq!("hello", huff_decode(&dst[2..6]));
833         assert_eq!(0x80 | 4, dst[6]);
834         assert_eq!("world", huff_decode(&dst[7..11]));
835 
836         dst.clear();
837 
838         match encoder.encode(Some(resume), &mut input, &mut (&mut dst).limit(max_len)) {
839             Encode::Full => {}
840             unexpected => panic!("resume returned unexpected: {:?}", unexpected),
841         }
842 
843         // Next is not indexed
844         assert_eq!(&[15, 47, 0x80 | 3], &dst[0..3]);
845         assert_eq!("zomg", huff_decode(&dst[3..6]));
846         assert_eq!(&[15, 47, 0x80 | 3], &dst[6..9]);
847         assert_eq!("sup", huff_decode(&dst[9..]));
848     }
849 
850     #[test]
851     #[ignore]
test_evicted_overflow()852     fn test_evicted_overflow() {
853         // Not sure what the best way to do this is.
854     }
855 
encode(e: &mut Encoder, hdrs: Vec<Header<Option<HeaderName>>>) -> BytesMut856     fn encode(e: &mut Encoder, hdrs: Vec<Header<Option<HeaderName>>>) -> BytesMut {
857         let mut dst = BytesMut::with_capacity(1024);
858         e.encode(None, &mut hdrs.into_iter(), &mut (&mut dst).limit(1024));
859         dst
860     }
861 
method(s: &str) -> Header<Option<HeaderName>>862     fn method(s: &str) -> Header<Option<HeaderName>> {
863         Header::Method(Method::from_bytes(s.as_bytes()).unwrap())
864     }
865 
header(name: &str, val: &str) -> Header<Option<HeaderName>>866     fn header(name: &str, val: &str) -> Header<Option<HeaderName>> {
867         let name = HeaderName::from_bytes(name.as_bytes()).unwrap();
868         let value = HeaderValue::from_bytes(val.as_bytes()).unwrap();
869 
870         Header::Field {
871             name: Some(name),
872             value,
873         }
874     }
875 
huff_decode(src: &[u8]) -> BytesMut876     fn huff_decode(src: &[u8]) -> BytesMut {
877         let mut buf = BytesMut::new();
878         huffman::decode(src, &mut buf).unwrap()
879     }
880 }
881