1use std::collections::VecDeque;
10
11use crate::error::H2Error;
12
13pub const MAX_HEADER_FIELDS: usize = 256;
19
20#[derive(Debug, Clone, PartialEq, Eq)]
22pub struct HeaderField {
23 pub name: Vec<u8>,
24 pub value: Vec<u8>,
25}
26
27impl HeaderField {
28 pub fn new(name: impl Into<Vec<u8>>, value: impl Into<Vec<u8>>) -> Self {
29 Self {
30 name: name.into(),
31 value: value.into(),
32 }
33 }
34
35 fn size(&self) -> usize {
38 self.name.len() + self.value.len() + 32
39 }
40}
41
42pub(crate) fn encode_prefix_int(buf: &mut Vec<u8>, value: u64, prefix_bits: u8, pattern: u8) {
45 let max = (1u64 << prefix_bits) - 1;
46 if value < max {
47 buf.push(pattern | value as u8);
48 } else {
49 buf.push(pattern | max as u8);
50 let mut remaining = value - max;
51 while remaining >= 128 {
52 buf.push(0x80 | (remaining & 0x7f) as u8);
53 remaining >>= 7;
54 }
55 buf.push(remaining as u8);
56 }
57}
58
59pub(crate) fn decode_prefix_int(buf: &[u8], prefix_bits: u8) -> Option<(u64, usize)> {
60 if buf.is_empty() {
61 return None;
62 }
63 let max = (1u64 << prefix_bits) - 1;
64 let value = u64::from(buf[0]) & max;
65 if value < max {
66 return Some((value, 1));
67 }
68 let mut value = max;
69 let mut shift = 0u32;
70 for (i, &b) in buf[1..].iter().enumerate() {
71 value += u64::from(b & 0x7f) << shift;
72 shift += 7;
73 if b & 0x80 == 0 {
74 return Some((value, i + 2));
75 }
76 if shift > 56 {
77 return None; }
79 }
80 None }
82
83const STATIC_TABLE: &[(&[u8], &[u8])] = &[
87 (b":authority", b""), (b":method", b"GET"), (b":method", b"POST"), (b":path", b"/"), (b":path", b"/index.html"), (b":scheme", b"http"), (b":scheme", b"https"), (b":status", b"200"), (b":status", b"204"), (b":status", b"206"), (b":status", b"304"), (b":status", b"400"), (b":status", b"404"), (b":status", b"500"), (b"accept-charset", b""), (b"accept-encoding", b"gzip, deflate"), (b"accept-language", b""), (b"accept-ranges", b""), (b"accept", b""), (b"access-control-allow-origin", b""), (b"age", b""), (b"allow", b""), (b"authorization", b""), (b"cache-control", b""), (b"content-disposition", b""), (b"content-encoding", b""), (b"content-language", b""), (b"content-length", b""), (b"content-location", b""), (b"content-range", b""), (b"content-type", b""), (b"cookie", b""), (b"date", b""), (b"etag", b""), (b"expect", b""), (b"expires", b""), (b"from", b""), (b"host", b""), (b"if-match", b""), (b"if-modified-since", b""), (b"if-none-match", b""), (b"if-range", b""), (b"if-unmodified-since", b""), (b"last-modified", b""), (b"link", b""), (b"location", b""), (b"max-forwards", b""), (b"proxy-authenticate", b""), (b"proxy-authorization", b""), (b"range", b""), (b"referer", b""), (b"refresh", b""), (b"retry-after", b""), (b"server", b""), (b"set-cookie", b""), (b"strict-transport-security", b""), (b"transfer-encoding", b""), (b"user-agent", b""), (b"vary", b""), (b"via", b""), (b"www-authenticate", b""), ];
149
150fn find_static_name_value(name: &[u8], value: &[u8]) -> Option<usize> {
153 STATIC_TABLE
154 .iter()
155 .position(|(n, v)| *n == name && *v == value)
156 .map(|i| i + 1) }
158
159fn find_static_name(name: &[u8]) -> Option<usize> {
162 STATIC_TABLE
163 .iter()
164 .position(|(n, _)| *n == name)
165 .map(|i| i + 1)
166}
167
168pub struct DynamicTable {
175 entries: VecDeque<HeaderField>,
176 size: usize,
177 max_size: usize,
178}
179
180impl DynamicTable {
181 pub fn new(max_size: usize) -> Self {
182 Self {
183 entries: VecDeque::new(),
184 size: 0,
185 max_size,
186 }
187 }
188
189 pub fn get(&self, index: usize) -> Option<&HeaderField> {
191 self.entries.get(index)
192 }
193
194 pub fn insert(&mut self, field: HeaderField) {
196 let entry_size = field.size();
197 while self.size + entry_size > self.max_size && !self.entries.is_empty() {
199 if let Some(evicted) = self.entries.pop_back() {
200 self.size -= evicted.size();
201 }
202 }
203 if entry_size > self.max_size {
205 self.entries.clear();
206 self.size = 0;
207 return;
208 }
209 self.entries.push_front(field);
210 self.size += entry_size;
211 }
212
213 pub fn set_max_size(&mut self, max_size: usize) {
215 self.max_size = max_size;
216 while self.size > self.max_size && !self.entries.is_empty() {
217 if let Some(evicted) = self.entries.pop_back() {
218 self.size -= evicted.size();
219 }
220 }
221 }
222
223 fn find_name_value(&self, name: &[u8], value: &[u8]) -> Option<usize> {
226 self.entries
227 .iter()
228 .position(|h| h.name == name && h.value == value)
229 .map(|i| i + 62) }
231
232 fn find_name(&self, name: &[u8]) -> Option<usize> {
235 self.entries
236 .iter()
237 .position(|h| h.name == name)
238 .map(|i| i + 62)
239 }
240
241 pub fn len(&self) -> usize {
242 self.entries.len()
243 }
244
245 pub fn is_empty(&self) -> bool {
246 self.entries.is_empty()
247 }
248}
249
250fn encode_string_literal(buf: &mut Vec<u8>, data: &[u8]) {
254 let huf_len = crate::huffman::encoded_len(data);
255 if huf_len < data.len() {
256 encode_prefix_int(buf, huf_len as u64, 7, 0x80);
258 crate::huffman::encode(data, buf);
259 } else {
260 encode_prefix_int(buf, data.len() as u64, 7, 0x00);
262 buf.extend_from_slice(data);
263 }
264}
265
266fn decode_string_literal(buf: &[u8]) -> Result<(Vec<u8>, usize), H2Error> {
268 if buf.is_empty() {
269 return Err(H2Error::CompressionError);
270 }
271 let huffman = buf[0] & 0x80 != 0;
272 let (str_len, n) = decode_prefix_int(buf, 7).ok_or(H2Error::CompressionError)?;
273 let str_len = str_len as usize;
274 let total = n + str_len;
275 if buf.len() < total {
276 return Err(H2Error::CompressionError);
277 }
278 let data = &buf[n..total];
279 let value = if huffman {
280 crate::huffman::decode(data)?
281 } else {
282 data.to_vec()
283 };
284 Ok((value, total))
285}
286
287pub struct Encoder {
291 dynamic_table: DynamicTable,
292 pending_min: Option<usize>,
297 pending_latest: Option<usize>,
298}
299
300impl Encoder {
301 pub fn new(max_table_size: usize) -> Self {
302 Encoder {
303 dynamic_table: DynamicTable::new(max_table_size),
304 pending_min: None,
305 pending_latest: None,
306 }
307 }
308
309 pub fn set_max_table_size(&mut self, new_size: usize, buf: &mut Vec<u8>) {
312 self.dynamic_table.set_max_size(new_size);
313 encode_prefix_int(buf, new_size as u64, 5, 0x20);
316 }
317
318 pub fn update_max_table_size(&mut self, new_size: usize) {
323 self.pending_min = Some(match self.pending_min {
324 Some(m) => m.min(new_size),
325 None => new_size,
326 });
327 self.pending_latest = Some(new_size);
328 }
329
330 pub fn encode(&mut self, headers: &[HeaderField], buf: &mut Vec<u8>) {
332 if let Some(latest) = self.pending_latest.take() {
336 let min = self.pending_min.take().unwrap_or(latest);
337 if min != latest {
338 self.dynamic_table.set_max_size(min);
339 encode_prefix_int(buf, min as u64, 5, 0x20);
340 }
341 self.dynamic_table.set_max_size(latest);
342 encode_prefix_int(buf, latest as u64, 5, 0x20);
343 }
344 for header in headers {
345 self.encode_header(header, buf);
346 }
347 }
348
349 fn encode_header(&mut self, header: &HeaderField, buf: &mut Vec<u8>) {
350 if let Some(index) = find_static_name_value(&header.name, &header.value) {
352 encode_prefix_int(buf, index as u64, 7, 0x80);
354 return;
355 }
356
357 if let Some(index) = self
359 .dynamic_table
360 .find_name_value(&header.name, &header.value)
361 {
362 encode_prefix_int(buf, index as u64, 7, 0x80);
363 return;
364 }
365
366 if let Some(name_index) = find_static_name(&header.name) {
368 encode_prefix_int(buf, name_index as u64, 6, 0x40);
371 encode_string_literal(buf, &header.value);
372 self.dynamic_table.insert(header.clone());
373 return;
374 }
375
376 if let Some(name_index) = self.dynamic_table.find_name(&header.name) {
378 encode_prefix_int(buf, name_index as u64, 6, 0x40);
379 encode_string_literal(buf, &header.value);
380 self.dynamic_table.insert(header.clone());
381 return;
382 }
383
384 buf.push(0x40);
387 encode_string_literal(buf, &header.name);
388 encode_string_literal(buf, &header.value);
389 self.dynamic_table.insert(header.clone());
390 }
391}
392
393pub struct Decoder {
397 dynamic_table: DynamicTable,
398 max_table_size: usize,
399}
400
401impl Decoder {
402 pub fn new(max_table_size: usize) -> Self {
403 Self {
404 dynamic_table: DynamicTable::new(max_table_size),
405 max_table_size,
406 }
407 }
408
409 pub fn decode(&mut self, buf: &[u8]) -> Result<Vec<HeaderField>, H2Error> {
411 let mut headers = Vec::new();
412 let mut pos = 0;
413 let mut seen_header = false;
417
418 while pos < buf.len() {
419 let first = buf[pos];
420
421 if first & 0x80 != 0 {
422 let (index, n) =
424 decode_prefix_int(&buf[pos..], 7).ok_or(H2Error::CompressionError)?;
425 pos += n;
426 if headers.len() >= MAX_HEADER_FIELDS {
427 return Err(H2Error::MaxSizeExceeded(format!(
428 "HPACK block exceeds MAX_HEADER_FIELDS ({MAX_HEADER_FIELDS})"
429 )));
430 }
431 let field = self.get_indexed(index as usize)?;
432 headers.push(field);
433 seen_header = true;
434 } else if first & 0x40 != 0 {
435 let (name_index, n) =
437 decode_prefix_int(&buf[pos..], 6).ok_or(H2Error::CompressionError)?;
438 pos += n;
439 let name = if name_index > 0 {
440 self.get_name(name_index as usize)?
441 } else {
442 let (name, consumed) = decode_string_literal(&buf[pos..])?;
443 pos += consumed;
444 name
445 };
446 let (value, consumed) = decode_string_literal(&buf[pos..])?;
447 pos += consumed;
448 if headers.len() >= MAX_HEADER_FIELDS {
449 return Err(H2Error::MaxSizeExceeded(format!(
450 "HPACK block exceeds MAX_HEADER_FIELDS ({MAX_HEADER_FIELDS})"
451 )));
452 }
453 let field = HeaderField {
454 name: name.clone(),
455 value,
456 };
457 self.dynamic_table.insert(field.clone());
458 headers.push(field);
459 seen_header = true;
460 } else if first & 0x20 != 0 {
461 if seen_header {
463 return Err(H2Error::CompressionError);
464 }
465 let (new_size, n) =
466 decode_prefix_int(&buf[pos..], 5).ok_or(H2Error::CompressionError)?;
467 pos += n;
468 let new_size = new_size as usize;
469 if new_size > self.max_table_size {
470 return Err(H2Error::CompressionError);
471 }
472 self.dynamic_table.set_max_size(new_size);
473 } else if first & 0x10 != 0 {
474 let (name_index, n) =
476 decode_prefix_int(&buf[pos..], 4).ok_or(H2Error::CompressionError)?;
477 pos += n;
478 let name = if name_index > 0 {
479 self.get_name(name_index as usize)?
480 } else {
481 let (name, consumed) = decode_string_literal(&buf[pos..])?;
482 pos += consumed;
483 name
484 };
485 let (value, consumed) = decode_string_literal(&buf[pos..])?;
486 pos += consumed;
487 if headers.len() >= MAX_HEADER_FIELDS {
488 return Err(H2Error::MaxSizeExceeded(format!(
489 "HPACK block exceeds MAX_HEADER_FIELDS ({MAX_HEADER_FIELDS})"
490 )));
491 }
492 headers.push(HeaderField { name, value });
493 seen_header = true;
494 } else {
496 let (name_index, n) =
498 decode_prefix_int(&buf[pos..], 4).ok_or(H2Error::CompressionError)?;
499 pos += n;
500 let name = if name_index > 0 {
501 self.get_name(name_index as usize)?
502 } else {
503 let (name, consumed) = decode_string_literal(&buf[pos..])?;
504 pos += consumed;
505 name
506 };
507 let (value, consumed) = decode_string_literal(&buf[pos..])?;
508 pos += consumed;
509 if headers.len() >= MAX_HEADER_FIELDS {
510 return Err(H2Error::MaxSizeExceeded(format!(
511 "HPACK block exceeds MAX_HEADER_FIELDS ({MAX_HEADER_FIELDS})"
512 )));
513 }
514 headers.push(HeaderField { name, value });
515 seen_header = true;
516 }
518 }
519
520 Ok(headers)
521 }
522
523 fn get_indexed(&self, index: usize) -> Result<HeaderField, H2Error> {
525 if index == 0 {
526 return Err(H2Error::CompressionError);
527 }
528 if index <= STATIC_TABLE.len() {
529 let (name, value) = STATIC_TABLE[index - 1];
530 Ok(HeaderField {
531 name: name.to_vec(),
532 value: value.to_vec(),
533 })
534 } else {
535 let dyn_index = index - STATIC_TABLE.len() - 1;
536 self.dynamic_table
537 .get(dyn_index)
538 .cloned()
539 .ok_or(H2Error::CompressionError)
540 }
541 }
542
543 fn get_name(&self, index: usize) -> Result<Vec<u8>, H2Error> {
545 if index == 0 {
546 return Err(H2Error::CompressionError);
547 }
548 if index <= STATIC_TABLE.len() {
549 Ok(STATIC_TABLE[index - 1].0.to_vec())
550 } else {
551 let dyn_index = index - STATIC_TABLE.len() - 1;
552 self.dynamic_table
553 .get(dyn_index)
554 .map(|h| h.name.clone())
555 .ok_or(H2Error::CompressionError)
556 }
557 }
558
559 pub fn set_max_table_size(&mut self, max_size: usize) {
561 self.max_table_size = max_size;
562 }
565}
566
567#[cfg(test)]
568mod tests {
569 use super::*;
570
571 #[test]
572 fn prefix_int_round_trip() {
573 for &(value, prefix_bits, pattern) in &[
574 (0u64, 7, 0x80u8),
575 (5, 7, 0x80),
576 (126, 7, 0x80),
577 (127, 7, 0x80),
578 (128, 7, 0x80),
579 (1000, 7, 0x80),
580 (0, 6, 0x40),
581 (62, 6, 0x40),
582 (63, 6, 0x40),
583 (64, 6, 0x40),
584 (255, 6, 0x40),
585 (0, 5, 0x20),
586 (31, 5, 0x20),
587 (32, 5, 0x20),
588 (4096, 5, 0x20),
589 (0, 4, 0x00),
590 (15, 4, 0x00),
591 (16, 4, 0x00),
592 ] {
593 let mut buf = Vec::new();
594 encode_prefix_int(&mut buf, value, prefix_bits, pattern);
595 let (decoded, len) = decode_prefix_int(&buf, prefix_bits).unwrap();
596 assert_eq!(
597 decoded, value,
598 "mismatch for value={value} prefix={prefix_bits}"
599 );
600 assert_eq!(len, buf.len());
601 let mask = !((1u8 << prefix_bits) - 1);
602 assert_eq!(buf[0] & mask, pattern & mask);
603 }
604 }
605
606 #[test]
607 fn static_table_size() {
608 assert_eq!(STATIC_TABLE.len(), 61);
609 }
610
611 #[test]
612 fn encode_decode_indexed() {
613 let mut encoder = Encoder::new(4096);
615 let mut decoder = Decoder::new(4096);
616 let headers = vec![HeaderField::new(b":method", b"GET")];
617 let mut buf = Vec::new();
618 encoder.encode(&headers, &mut buf);
619 let decoded = decoder.decode(&buf).unwrap();
620 assert_eq!(decoded, headers);
621 }
622
623 #[test]
624 fn encode_decode_name_reference() {
625 let mut encoder = Encoder::new(4096);
627 let mut decoder = Decoder::new(4096);
628 let headers = vec![HeaderField::new(b":path", b"/foo")];
629 let mut buf = Vec::new();
630 encoder.encode(&headers, &mut buf);
631 let decoded = decoder.decode(&buf).unwrap();
632 assert_eq!(decoded, headers);
633 }
634
635 #[test]
636 fn encode_decode_literal() {
637 let mut encoder = Encoder::new(4096);
638 let mut decoder = Decoder::new(4096);
639 let headers = vec![HeaderField::new(b"x-custom", b"value123")];
640 let mut buf = Vec::new();
641 encoder.encode(&headers, &mut buf);
642 let decoded = decoder.decode(&buf).unwrap();
643 assert_eq!(decoded, headers);
644 }
645
646 #[test]
647 fn encode_decode_multiple_headers() {
648 let mut encoder = Encoder::new(4096);
649 let mut decoder = Decoder::new(4096);
650 let headers = vec![
651 HeaderField::new(b":method", b"GET"),
652 HeaderField::new(b":path", b"/"),
653 HeaderField::new(b":scheme", b"https"),
654 HeaderField::new(b":authority", b"example.com"),
655 HeaderField::new(b"accept", b"*/*"),
656 HeaderField::new(b"x-request-id", b"abc123"),
657 ];
658 let mut buf = Vec::new();
659 encoder.encode(&headers, &mut buf);
660 let decoded = decoder.decode(&buf).unwrap();
661 assert_eq!(decoded, headers);
662 }
663
664 #[test]
665 fn dynamic_table_reuse() {
666 let mut encoder = Encoder::new(4096);
667 let mut decoder = Decoder::new(4096);
668
669 let headers1 = vec![
671 HeaderField::new(b":method", b"GET"),
672 HeaderField::new(b"x-token", b"abc"),
673 ];
674 let mut buf1 = Vec::new();
675 encoder.encode(&headers1, &mut buf1);
676 let decoded1 = decoder.decode(&buf1).unwrap();
677 assert_eq!(decoded1, headers1);
678
679 let headers2 = vec![
681 HeaderField::new(b":method", b"GET"),
682 HeaderField::new(b"x-token", b"abc"),
683 ];
684 let mut buf2 = Vec::new();
685 encoder.encode(&headers2, &mut buf2);
686 let decoded2 = decoder.decode(&buf2).unwrap();
687 assert_eq!(decoded2, headers2);
688
689 assert!(buf2.len() <= buf1.len());
691 }
692
693 #[test]
694 fn dynamic_table_eviction() {
695 let mut encoder = Encoder::new(64);
697 let mut decoder = Decoder::new(64);
698
699 let headers = vec![HeaderField::new(
700 b"x-long-header-name",
701 b"a-somewhat-long-value",
702 )];
703 let mut buf = Vec::new();
704 encoder.encode(&headers, &mut buf);
705 let decoded = decoder.decode(&buf).unwrap();
706 assert_eq!(decoded, headers);
707 }
708
709 #[test]
710 fn encode_decode_status_200() {
711 let mut encoder = Encoder::new(4096);
712 let mut decoder = Decoder::new(4096);
713 let headers = vec![
714 HeaderField::new(b":status", b"200"),
715 HeaderField::new(b"content-type", b"text/plain"),
716 ];
717 let mut buf = Vec::new();
718 encoder.encode(&headers, &mut buf);
719 let decoded = decoder.decode(&buf).unwrap();
720 assert_eq!(decoded, headers);
721 }
722
723 #[test]
724 fn table_size_update() {
725 let mut encoder = Encoder::new(4096);
726 let mut decoder = Decoder::new(4096);
727
728 let mut buf = Vec::new();
729 encoder.set_max_table_size(256, &mut buf);
730 encoder.encode(&[HeaderField::new(b":method", b"GET")], &mut buf);
731 let decoded = decoder.decode(&buf).unwrap();
732 assert_eq!(decoded, vec![HeaderField::new(b":method", b"GET")]);
733 }
734
735 #[test]
736 fn encoder_emits_min_then_latest_when_multiple_updates_pending() {
737 let mut encoder = Encoder::new(4096);
741 encoder.update_max_table_size(4096);
742 encoder.update_max_table_size(1024); encoder.update_max_table_size(2048); let mut buf = Vec::new();
746 encoder.encode(&[HeaderField::new(b":method", b"GET")], &mut buf);
747
748 let (first, n) = decode_prefix_int(&buf, 5).unwrap();
750 assert_eq!(first, 1024, "expected min (1024) first");
751 let (second, _) = decode_prefix_int(&buf[n..], 5).unwrap();
752 assert_eq!(second, 2048, "expected latest (2048) second");
753 }
754
755 #[test]
756 fn encoder_single_update_when_min_equals_latest() {
757 let mut encoder = Encoder::new(4096);
758 encoder.update_max_table_size(2048);
759 encoder.update_max_table_size(2048); let mut buf = Vec::new();
762 encoder.encode(&[HeaderField::new(b":method", b"GET")], &mut buf);
763
764 let (size, n) = decode_prefix_int(&buf, 5).unwrap();
766 assert_eq!(size, 2048);
767 assert_eq!(buf[n], 0x82);
770 }
771
772 #[test]
773 fn decoder_caps_at_max_header_fields() {
774 let mut decoder = Decoder::new(4096);
777 let block: Vec<u8> = std::iter::repeat_n(0x82u8, MAX_HEADER_FIELDS + 1).collect();
778 let err = decoder.decode(&block).err().unwrap();
779 assert!(matches!(err, H2Error::MaxSizeExceeded(_)));
780 }
781
782 #[test]
783 fn decoder_rejects_table_size_update_after_header() {
784 let mut decoder = Decoder::new(4096);
787 let block = vec![0x82, 0x20]; let err = decoder.decode(&block).err().unwrap();
789 assert!(matches!(err, H2Error::CompressionError));
790 }
791
792 #[test]
793 fn decoder_accepts_table_size_update_before_header() {
794 let mut decoder = Decoder::new(4096);
796 let block = vec![0x20, 0x82]; let headers = decoder.decode(&block).unwrap();
798 assert_eq!(headers.len(), 1);
799 }
800
801 #[test]
802 fn rfc7541_appendix_c1_integer_examples() {
803 let mut buf = Vec::new();
805 encode_prefix_int(&mut buf, 10, 5, 0x00);
806 assert_eq!(buf, vec![0x0a]);
807
808 let mut buf = Vec::new();
810 encode_prefix_int(&mut buf, 1337, 5, 0x00);
811 assert_eq!(buf, vec![0x1f, 0x9a, 0x0a]);
812
813 let mut buf = Vec::new();
815 encode_prefix_int(&mut buf, 42, 8, 0x00);
816 assert_eq!(buf, vec![0x2a]);
817 }
818}