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