1use crate::table::{DynTable, Name, STATIC_TABLE};
4use crate::{decode_integer, field_size, read_string, Error};
5
6#[derive(Debug, Clone)]
8pub struct Decoder {
9 table: DynTable,
10 max_allowed: usize,
12 max_list: usize,
14 name_buf: Vec<u8>,
15 value_buf: Vec<u8>,
16}
17
18impl Decoder {
19 pub fn new(max_table_size: usize, max_list_size: usize) -> Self {
22 Decoder {
23 table: DynTable::new(max_table_size),
24 max_allowed: max_table_size,
25 max_list: max_list_size,
26 name_buf: Vec::new(),
27 value_buf: Vec::new(),
28 }
29 }
30
31 pub fn set_max_allowed(&mut self, max: usize) {
34 self.max_allowed = max;
35 if self.table.max() > max {
36 self.table.set_max(max);
37 }
38 }
39
40 pub fn set_max_list_size(&mut self, max: usize) {
42 self.max_list = max;
43 }
44
45 pub fn table_size(&self) -> usize {
47 self.table.size()
48 }
49
50 pub fn table_max_size(&self) -> usize {
52 self.table.max()
53 }
54
55 pub fn table_len(&self) -> usize {
57 self.table.len()
58 }
59
60 pub fn table_entry(&self, i: usize) -> Option<(&[u8], &[u8])> {
62 self.table.get(i)
63 }
64
65 #[inline]
66 fn lookup(&self, idx: usize) -> Result<(&[u8], &[u8]), Error> {
67 if idx == 0 {
68 Err(Error::InvalidIndex)
69 } else if idx <= STATIC_TABLE.len() {
70 Ok(STATIC_TABLE[idx - 1])
71 } else {
72 self.table.get(idx - STATIC_TABLE.len() - 1).ok_or(Error::InvalidIndex)
73 }
74 }
75
76 pub fn decode(&mut self, block: &[u8], emit: &mut dyn FnMut(&[u8], &[u8])) -> Result<(), Error> {
81 let mut pos = 0;
82 let mut size = 0usize;
83 let mut over = false;
84 let mut seen_field = false;
85 while pos < block.len() {
86 let b = block[pos];
87 if b & 0x80 != 0 {
88 let idx = decode_integer(block, &mut pos, 7)?;
90 let (n, v) = self.lookup(idx)?;
91 seen_field = true;
92 size += field_size(n, v);
93 if size > self.max_list {
94 over = true;
95 }
96 if !over {
97 emit(n, v);
98 }
99 continue;
100 }
101 if b & 0xe0 == 0x20 {
102 if seen_field {
104 return Err(Error::InvalidTableSizeUpdate);
105 }
106 let s = decode_integer(block, &mut pos, 5)?;
107 if s > self.max_allowed {
108 return Err(Error::InvalidTableSizeUpdate);
109 }
110 self.table.set_max(s);
111 continue;
112 }
113 let indexing = b & 0x40 != 0;
115 let idx = decode_integer(block, &mut pos, if indexing { 6 } else { 4 })?;
116 seen_field = true;
117 let dyn_name = idx > STATIC_TABLE.len();
118 if dyn_name && idx - STATIC_TABLE.len() - 1 >= self.table.len() {
119 return Err(Error::InvalidIndex);
120 }
121 let lit_name: &[u8] = if idx == 0 { read_string(block, &mut pos, &mut self.name_buf)? } else { &[] };
122 let value = read_string(block, &mut pos, &mut self.value_buf)?;
123 let name: &[u8] = if idx == 0 {
124 lit_name
125 } else if dyn_name {
126 self.table.get(idx - STATIC_TABLE.len() - 1).map_or(&[][..], |e| e.0)
127 } else {
128 STATIC_TABLE[idx - 1].0
129 };
130 size += field_size(name, value);
131 if size > self.max_list {
132 over = true;
133 }
134 if !indexing || field_size(name, value) > self.table.max() {
135 if !over {
137 emit(name, value);
138 }
139 if indexing {
140 self.table.clear(); }
142 continue;
143 }
144 let src = if idx == 0 {
145 Name::Bytes(lit_name)
146 } else if dyn_name {
147 Name::Dyn(idx - STATIC_TABLE.len() - 1)
148 } else {
149 Name::Bytes(STATIC_TABLE[idx - 1].0)
150 };
151 self.table.insert(src, value);
152 if !over {
153 if let Some((n, v)) = self.table.get(0) {
154 emit(n, v);
155 }
156 }
157 }
158 if over {
159 Err(Error::HeaderListTooLarge)
160 } else {
161 Ok(())
162 }
163 }
164}