• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use std::collections::{HashMap, VecDeque};
15 
16 use crate::h3::qpack::error::QpackError;
17 
18 /// The [`Dynamic Table`][dynamic_table] implementation of [QPACK].
19 ///
20 /// [dynamic_table]: https://www.rfc-editor.org/rfc/rfc9204.html#name-dynamic-table
21 /// [QPACK]: https://www.rfc-editor.org/rfc/rfc9204.html
22 /// # Introduction
23 /// The dynamic table consists of a list of field lines maintained in first-in,
24 /// first-out order. A QPACK encoder and decoder share a dynamic table that is
25 /// initially empty. The encoder adds entries to the dynamic table and sends
26 /// them to the decoder via instructions on the encoder stream
27 ///
28 /// The dynamic table can contain duplicate entries (i.e., entries with the same
29 /// name and same value). Therefore, duplicate entries MUST NOT be treated as an
30 /// error by the decoder.
31 ///
32 /// Dynamic table entries can have empty values.
33 
34 pub(crate) struct TableSearcher<'a> {
35     dynamic: &'a DynamicTable,
36 }
37 
38 #[derive(Eq, PartialEq, Copy, Clone)]
39 pub(crate) enum SearchResult {
40     StaticIndex(usize),
41     StaticNameIndex(usize),
42     DynamicIndex(usize),
43     DynamicNameIndex(usize),
44     NotFound,
45 }
46 
47 impl<'a> TableSearcher<'a> {
new(dynamic: &'a DynamicTable) -> Self48     pub(crate) fn new(dynamic: &'a DynamicTable) -> Self {
49         Self { dynamic }
50     }
51 
search_in_static(&self, header: &NameField, value: &str) -> TableIndex52     pub(crate) fn search_in_static(&self, header: &NameField, value: &str) -> TableIndex {
53         StaticTable::index(header, value)
54     }
55 
search_in_dynamic( &self, header: &NameField, value: &str, allow_block: bool, ) -> TableIndex56     pub(crate) fn search_in_dynamic(
57         &self,
58         header: &NameField,
59         value: &str,
60         allow_block: bool,
61     ) -> TableIndex {
62         self.dynamic.index(header, value, allow_block)
63     }
64 
find_field_static(&self, index: usize) -> Option<(NameField, String)>65     pub(crate) fn find_field_static(&self, index: usize) -> Option<(NameField, String)> {
66         match StaticTable::field(index) {
67             x @ Some((_, _)) => x,
68             _ => None,
69         }
70     }
71 
find_field_name_static(&self, index: usize) -> Option<NameField>72     pub(crate) fn find_field_name_static(&self, index: usize) -> Option<NameField> {
73         StaticTable::field_name(index)
74     }
75 
find_field_dynamic(&self, index: usize) -> Option<(NameField, String)>76     pub(crate) fn find_field_dynamic(&self, index: usize) -> Option<(NameField, String)> {
77         self.dynamic.field(index)
78     }
79 
find_field_name_dynamic(&self, index: usize) -> Option<NameField>80     pub(crate) fn find_field_name_dynamic(&self, index: usize) -> Option<NameField> {
81         self.dynamic.field_name(index)
82     }
83 }
84 
85 #[derive(Clone, Eq, PartialEq)]
86 struct DynamicField {
87     index: u64,
88     name: NameField,
89     value: String,
90     tracked: usize,
91 }
92 
93 impl DynamicField {
index(&self) -> u6494     pub(crate) fn index(&self) -> u64 {
95         self.index
96     }
97 
name(&self) -> &NameField98     pub(crate) fn name(&self) -> &NameField {
99         &self.name
100     }
101 
value(&self) -> &str102     pub(crate) fn value(&self) -> &str {
103         self.value.as_str()
104     }
105 
size(&self) -> usize106     pub(crate) fn size(&self) -> usize {
107         self.name.len() + self.value.len() + 32
108     }
109 
is_tracked(&self) -> bool110     pub(crate) fn is_tracked(&self) -> bool {
111         self.tracked > 0
112     }
113 }
114 
115 pub struct DynamicTable {
116     queue: VecDeque<DynamicField>,
117     // The used_cap of the dynamic table is the sum of the used_cap of its entries
118     used_cap: usize,
119     capacity: usize,
120     insert_count: usize,
121     remove_count: usize,
122     known_received_count: u64,
123 }
124 
125 impl DynamicTable {
with_empty() -> Self126     pub fn with_empty() -> Self {
127         Self {
128             queue: VecDeque::new(),
129             used_cap: 0,
130             capacity: 0,
131             insert_count: 0,
132             remove_count: 0,
133             known_received_count: 0,
134         }
135     }
136 
update_capacity(&mut self, new_cap: usize) -> Option<usize>137     pub(crate) fn update_capacity(&mut self, new_cap: usize) -> Option<usize> {
138         let mut updated = None;
139         if new_cap < self.capacity {
140             let required = self.capacity - new_cap;
141             if let Some(size) = self.can_evict(required) {
142                 self.evict_drained(size);
143                 self.capacity = new_cap;
144                 updated = Some(new_cap);
145             }
146         } else {
147             self.capacity = new_cap;
148             updated = Some(new_cap);
149         }
150         updated
151     }
152 
insert_count(&self) -> usize153     pub(crate) fn insert_count(&self) -> usize {
154         self.insert_count
155     }
156 
track_field(&mut self, index: usize)157     pub(crate) fn track_field(&mut self, index: usize) {
158         if let Some(field) = self.queue.get_mut(index - self.remove_count) {
159             field.tracked += 1;
160         } else {
161             unreachable!()
162         }
163     }
164 
untracked_field(&mut self, index: usize)165     pub(crate) fn untracked_field(&mut self, index: usize) {
166         if let Some(field) = self.queue.get_mut(index - self.remove_count) {
167             assert!(field.tracked > 0);
168             field.tracked -= 1;
169         } else {
170             unreachable!()
171         }
172     }
173 
increase_known_receive_count(&mut self, increment: usize)174     pub(crate) fn increase_known_receive_count(&mut self, increment: usize) {
175         self.known_received_count += (increment - 1) as u64;
176         // TODO 替换成error
177         assert!(self.known_received_count < (self.insert_count as u64))
178     }
179 
size(&self) -> usize180     pub(crate) fn size(&self) -> usize {
181         self.used_cap
182     }
183 
capacity(&self) -> usize184     pub(crate) fn capacity(&self) -> usize {
185         self.capacity
186     }
187 
can_evict(&mut self, required: usize) -> Option<usize>188     pub(crate) fn can_evict(&mut self, required: usize) -> Option<usize> {
189         if required > self.capacity {
190             return None;
191         }
192         let bound = self.capacity - required;
193         let mut can_evict = 0;
194         let mut used_cap = self.used_cap;
195         while !self.queue.is_empty() && used_cap > bound {
196             if let Some(to_evict) = self.queue.front() {
197                 if to_evict.is_tracked() || to_evict.index() > self.known_recved_count() {
198                     return None;
199                 }
200                 used_cap -= to_evict.size();
201                 can_evict += 1;
202             }
203         }
204         Some(can_evict)
205     }
206 
207     // Note ensure that there are enough entries in the queue before the expulsion.
evict_drained(&mut self, size: usize)208     pub(crate) fn evict_drained(&mut self, size: usize) {
209         let mut to_evict = size;
210         while to_evict > 0 {
211             if let Some(field) = self.queue.pop_front() {
212                 self.used_cap -= field.size();
213                 self.remove_count += 1;
214             } else {
215                 unreachable!()
216             }
217             to_evict -= 1;
218         }
219     }
220 
known_recved_count(&self) -> u64221     pub(crate) fn known_recved_count(&self) -> u64 {
222         self.known_received_count
223     }
224 
max_entries(&self) -> usize225     pub(crate) fn max_entries(&self) -> usize {
226         self.capacity / 32
227     }
228 
229     /// Updates `DynamicTable` by a given `Header` and value pair.
update(&mut self, field: NameField, value: String) -> usize230     pub(crate) fn update(&mut self, field: NameField, value: String) -> usize {
231         let field = DynamicField {
232             index: self.insert_count() as u64,
233             name: field,
234             value,
235             tracked: 0,
236         };
237         let size = field.size();
238         let index = field.index();
239         self.queue.push_back(field);
240         self.insert_count += 1;
241         self.used_cap += size;
242         index as usize
243     }
244 
245     /// Tries to get the index of a `Header`.
index(&self, header: &NameField, value: &str, allow_block: bool) -> TableIndex246     fn index(&self, header: &NameField, value: &str, allow_block: bool) -> TableIndex {
247         let mut index = TableIndex::None;
248 
249         for field in self.queue.iter() {
250             // 从queue的头开始迭代,index从小到大,找到最新(大)的index
251             if field.index() > self.known_recved_count() && !allow_block {
252                 break;
253             }
254             if header == field.name() {
255                 // find latest then return
256                 index = if value == field.value() {
257                     TableIndex::Field(field.index() as usize)
258                 } else {
259                     TableIndex::FieldName(field.index() as usize)
260                 }
261             }
262         }
263         index
264     }
265 
field(&self, index: usize) -> Option<(NameField, String)>266     pub(crate) fn field(&self, index: usize) -> Option<(NameField, String)> {
267         self.queue
268             .get(index - self.remove_count)
269             .cloned()
270             .map(|field| (field.name, field.value))
271     }
272 
field_name(&self, index: usize) -> Option<NameField>273     pub(crate) fn field_name(&self, index: usize) -> Option<NameField> {
274         self.queue
275             .get(index - self.remove_count)
276             .map(|field| field.name().clone())
277     }
278 
279     /// Updates `DynamicTable`'s size.
update_size(&mut self, max_size: usize)280     pub(crate) fn update_size(&mut self, max_size: usize) {
281         self.capacity = max_size;
282         self.fit_size();
283     }
284 
285     /// Adjusts dynamic table content to fit its size.
fit_size(&mut self)286     fn fit_size(&mut self) {
287         while self.used_cap > self.capacity && !self.queue.is_empty() {
288             let field = self.queue.pop_front().unwrap();
289             self.remove_count += 1;
290             self.used_cap -= field.size();
291         }
292     }
293 }
294 
295 #[derive(PartialEq, Copy, Clone)]
296 pub(crate) enum TableIndex {
297     Field(usize),
298     FieldName(usize),
299     None,
300 }
301 
302 /// The [`Static Table`][static_table] implementation of [QPACK].
303 ///
304 /// [static_table]: https://www.rfc-editor.org/rfc/rfc9204.html#static-table
305 /// [QPACK]: https://www.rfc-editor.org/rfc/rfc9204.html
306 ///
307 /// # Introduction
308 /// The static table consists of a predefined list of field lines,
309 /// each of which has a fixed index over time.
310 /// All entries in the static table have a name and a value.
311 /// However, values can be empty (that is, have a length of 0). Each entry is
312 /// identified by a unique index.
313 /// Note that the QPACK static table is indexed from 0,
314 /// whereas the HPACK static table is indexed from 1.
315 /// When the decoder encounters an invalid static table
316 /// index in a field line format, it MUST treat this
317 /// as a connection error of type QpackDecompressionFailed.
318 /// If this index is received on the encoder stream,
319 /// this MUST be treated as a connection error of type QpackEncoderStreamError.
320 
321 struct StaticTable;
322 
323 impl StaticTable {
324     /// Gets a `Field` by the given index.
field_name(index: usize) -> Option<NameField>325     fn field_name(index: usize) -> Option<NameField> {
326         match index {
327             0 => Some(NameField::Authority),
328             1 => Some(NameField::Path),
329             2 => Some(NameField::Other(String::from("age"))),
330             3 => Some(NameField::Other(String::from("content-disposition"))),
331             4 => Some(NameField::Other(String::from("content-length"))),
332             5 => Some(NameField::Other(String::from("cookie"))),
333             6 => Some(NameField::Other(String::from("date"))),
334             7 => Some(NameField::Other(String::from("etag"))),
335             8 => Some(NameField::Other(String::from("if-modified-since"))),
336             9 => Some(NameField::Other(String::from("if-none-match"))),
337             10 => Some(NameField::Other(String::from("last-modified"))),
338             11 => Some(NameField::Other(String::from("link"))),
339             12 => Some(NameField::Other(String::from("location"))),
340             13 => Some(NameField::Other(String::from("referer"))),
341             14 => Some(NameField::Other(String::from("set-cookie"))),
342             15..=21 => Some(NameField::Method),
343             22..=23 => Some(NameField::Scheme),
344             24..=28 => Some(NameField::Status),
345             29..=30 => Some(NameField::Other(String::from("accept"))),
346             31 => Some(NameField::Other(String::from("accept-encoding"))),
347             32 => Some(NameField::Other(String::from("accept-ranges"))),
348             33..=34 => Some(NameField::Other(String::from(
349                 "access-control-allow-headers",
350             ))),
351             35 => Some(NameField::Other(String::from(
352                 "access-control-allow-origin",
353             ))),
354             36..=41 => Some(NameField::Other(String::from("cache-control"))),
355             42..=43 => Some(NameField::Other(String::from("content-encoding"))),
356             44..=54 => Some(NameField::Other(String::from("content-type"))),
357             55 => Some(NameField::Other(String::from("range"))),
358             56..=58 => Some(NameField::Other(String::from("strict-transport-security"))),
359             59..=60 => Some(NameField::Other(String::from("vary"))),
360             61 => Some(NameField::Other(String::from("x-content-type-options"))),
361             62 => Some(NameField::Other(String::from("x-xss-protection"))),
362             63..=71 => Some(NameField::Status),
363             72 => Some(NameField::Other(String::from("accept-language"))),
364             73..=74 => Some(NameField::Other(String::from(
365                 "access-control-allow-credentials",
366             ))),
367             75 => Some(NameField::Other(String::from(
368                 "access-control-allow-headers",
369             ))),
370             76..=78 => Some(NameField::Other(String::from(
371                 "access-control-allow-methods",
372             ))),
373             79 => Some(NameField::Other(String::from(
374                 "access-control-expose-headers",
375             ))),
376             80 => Some(NameField::Other(String::from(
377                 "access-control-request-headers",
378             ))),
379             81..=82 => Some(NameField::Other(String::from(
380                 "access-control-request-method",
381             ))),
382             83 => Some(NameField::Other(String::from("alt-svc"))),
383             84 => Some(NameField::Other(String::from("authorization"))),
384             85 => Some(NameField::Other(String::from("content-security-policy"))),
385             86 => Some(NameField::Other(String::from("early-data"))),
386             87 => Some(NameField::Other(String::from("expect-ct"))),
387             88 => Some(NameField::Other(String::from("forwarded"))),
388             89 => Some(NameField::Other(String::from("if-range"))),
389             90 => Some(NameField::Other(String::from("origin"))),
390             91 => Some(NameField::Other(String::from("purpose"))),
391             92 => Some(NameField::Other(String::from("server"))),
392             93 => Some(NameField::Other(String::from("timing-allow-origin"))),
393             94 => Some(NameField::Other(String::from("upgrade-insecure-requests"))),
394             95 => Some(NameField::Other(String::from("user-agent"))),
395             96 => Some(NameField::Other(String::from("x-forwarded-for"))),
396             97..=98 => Some(NameField::Other(String::from("x-frame-options"))),
397             _ => None,
398         }
399     }
400 
401     /// Tries to get a `Field` and a value by the given index.
field(index: usize) -> Option<(NameField, String)>402     fn field(index: usize) -> Option<(NameField, String)> {
403         match index {
404             1 => Some((NameField::Path, String::from("/"))),
405             2 => Some((NameField::Other(String::from("age")), String::from("0"))),
406             4 => Some((
407                 NameField::Other(String::from("content-length")),
408                 String::from("0"),
409             )),
410             15 => Some((NameField::Method, String::from("CONNECT"))),
411             16 => Some((NameField::Method, String::from("DELETE"))),
412             17 => Some((NameField::Method, String::from("GET"))),
413             18 => Some((NameField::Method, String::from("HEAD"))),
414             19 => Some((NameField::Method, String::from("OPTIONS"))),
415             20 => Some((NameField::Method, String::from("POST"))),
416             21 => Some((NameField::Method, String::from("PUT"))),
417             22 => Some((NameField::Scheme, String::from("http"))),
418             23 => Some((NameField::Scheme, String::from("https"))),
419             24 => Some((NameField::Status, String::from("103"))),
420             25 => Some((NameField::Status, String::from("200"))),
421             26 => Some((NameField::Status, String::from("304"))),
422             27 => Some((NameField::Status, String::from("404"))),
423             28 => Some((NameField::Status, String::from("503"))),
424             29 => Some((
425                 NameField::Other(String::from("accept")),
426                 String::from("*/*"),
427             )),
428             30 => Some((
429                 NameField::Other(String::from("accept")),
430                 String::from("application/dns-message"),
431             )),
432             31 => Some((
433                 NameField::Other(String::from("accept-encoding")),
434                 String::from("gzip, deflate, br"),
435             )),
436             32 => Some((
437                 NameField::Other(String::from("accept-ranges")),
438                 String::from("bytes"),
439             )),
440             33 => Some((
441                 NameField::Other(String::from("access-control-allow-headers")),
442                 String::from("cache-control"),
443             )),
444             34 => Some((
445                 NameField::Other(String::from("access-control-allow-headers")),
446                 String::from("content-type"),
447             )),
448             35 => Some((
449                 NameField::Other(String::from("access-control-allow-origin")),
450                 String::from("*"),
451             )),
452             36 => Some((
453                 NameField::Other(String::from("cache-control")),
454                 String::from("max-age=0"),
455             )),
456             37 => Some((
457                 NameField::Other(String::from("cache-control")),
458                 String::from("max-age=2592000"),
459             )),
460             38 => Some((
461                 NameField::Other(String::from("cache-control")),
462                 String::from("max-age=604800"),
463             )),
464             39 => Some((
465                 NameField::Other(String::from("cache-control")),
466                 String::from("no-cache"),
467             )),
468             40 => Some((
469                 NameField::Other(String::from("cache-control")),
470                 String::from("no-store"),
471             )),
472             41 => Some((
473                 NameField::Other(String::from("cache-control")),
474                 String::from("public, max-age=31536000"),
475             )),
476             42 => Some((
477                 NameField::Other(String::from("content-encoding")),
478                 String::from("br"),
479             )),
480             43 => Some((
481                 NameField::Other(String::from("content-encoding")),
482                 String::from("gzip"),
483             )),
484             44 => Some((
485                 NameField::Other(String::from("content-type")),
486                 String::from("application/dns-message"),
487             )),
488             45 => Some((
489                 NameField::Other(String::from("content-type")),
490                 String::from("application/javascript"),
491             )),
492             46 => Some((
493                 NameField::Other(String::from("content-type")),
494                 String::from("application/json"),
495             )),
496             47 => Some((
497                 NameField::Other(String::from("content-type")),
498                 String::from("application/x-www-form-urlencoded"),
499             )),
500             48 => Some((
501                 NameField::Other(String::from("content-type")),
502                 String::from("image/gif"),
503             )),
504             49 => Some((
505                 NameField::Other(String::from("content-type")),
506                 String::from("image/jpeg"),
507             )),
508             50 => Some((
509                 NameField::Other(String::from("content-type")),
510                 String::from("image/png"),
511             )),
512             51 => Some((
513                 NameField::Other(String::from("content-type")),
514                 String::from("text/css"),
515             )),
516             52 => Some((
517                 NameField::Other(String::from("content-type")),
518                 String::from("text/html; charset=utf-8"),
519             )),
520             53 => Some((
521                 NameField::Other(String::from("content-type")),
522                 String::from("text/plain"),
523             )),
524             54 => Some((
525                 NameField::Other(String::from("content-type")),
526                 String::from("text/plain;charset=utf-8"),
527             )),
528             55 => Some((
529                 NameField::Other(String::from("range")),
530                 String::from("bytes=0-"),
531             )),
532             56 => Some((
533                 NameField::Other(String::from("strict-transport-security")),
534                 String::from("max-age=31536000"),
535             )),
536             57 => Some((
537                 NameField::Other(String::from("strict-transport-security")),
538                 String::from("max-age=31536000; includesubdomains"),
539             )),
540             58 => Some((
541                 NameField::Other(String::from("strict-transport-security")),
542                 String::from("max-age=31536000; includesubdomains; preload"),
543             )),
544             59 => Some((
545                 NameField::Other(String::from("vary")),
546                 String::from("accept-encoding"),
547             )),
548             60 => Some((
549                 NameField::Other(String::from("vary")),
550                 String::from("origin"),
551             )),
552             61 => Some((
553                 NameField::Other(String::from("x-content-type-options")),
554                 String::from("nosniff"),
555             )),
556             62 => Some((
557                 NameField::Other(String::from("x-xss-protection")),
558                 String::from("1; mode=block"),
559             )),
560             63 => Some((NameField::Status, String::from("100"))),
561             64 => Some((NameField::Status, String::from("204"))),
562             65 => Some((NameField::Status, String::from("206"))),
563             66 => Some((NameField::Status, String::from("302"))),
564             67 => Some((NameField::Status, String::from("400"))),
565             68 => Some((NameField::Status, String::from("403"))),
566             69 => Some((NameField::Status, String::from("421"))),
567             70 => Some((NameField::Status, String::from("425"))),
568             71 => Some((NameField::Status, String::from("500"))),
569             73 => Some((
570                 NameField::Other(String::from("access-control-allow-credentials")),
571                 String::from("FALSE"),
572             )),
573             74 => Some((
574                 NameField::Other(String::from("access-control-allow-credentials")),
575                 String::from("TRUE"),
576             )),
577             75 => Some((
578                 NameField::Other(String::from("access-control-allow-headers")),
579                 String::from("*"),
580             )),
581             76 => Some((
582                 NameField::Other(String::from("access-control-allow-methods")),
583                 String::from("get"),
584             )),
585             77 => Some((
586                 NameField::Other(String::from("access-control-allow-methods")),
587                 String::from("get, post, options"),
588             )),
589             78 => Some((
590                 NameField::Other(String::from("access-control-allow-methods")),
591                 String::from("options"),
592             )),
593             79 => Some((
594                 NameField::Other(String::from("access-control-expose-headers")),
595                 String::from("content-length"),
596             )),
597             80 => Some((
598                 NameField::Other(String::from("access-control-request-headers")),
599                 String::from("content-type"),
600             )),
601             81 => Some((
602                 NameField::Other(String::from("access-control-request-method")),
603                 String::from("get"),
604             )),
605             82 => Some((
606                 NameField::Other(String::from("access-control-request-method")),
607                 String::from("post"),
608             )),
609             83 => Some((
610                 NameField::Other(String::from("alt-svc")),
611                 String::from("clear"),
612             )),
613             85 => Some((
614                 NameField::Other(String::from("content-security-policy")),
615                 String::from("script-src 'none'; object-src 'none'; base-uri 'none'"),
616             )),
617             86 => Some((
618                 NameField::Other(String::from("early-data")),
619                 String::from("1"),
620             )),
621             91 => Some((
622                 NameField::Other(String::from("purpose")),
623                 String::from("prefetch"),
624             )),
625             93 => Some((
626                 NameField::Other(String::from("timing-allow-origin")),
627                 String::from("*"),
628             )),
629             94 => Some((
630                 NameField::Other(String::from("upgrade-insecure-requests")),
631                 String::from("1"),
632             )),
633             97 => Some((
634                 NameField::Other(String::from("x-frame-options")),
635                 String::from("deny"),
636             )),
637             98 => Some((
638                 NameField::Other(String::from("x-frame-options")),
639                 String::from("sameorigin"),
640             )),
641             _ => None,
642         }
643     }
644 
index(field: &NameField, value: &str) -> TableIndex645     fn index(field: &NameField, value: &str) -> TableIndex {
646         match (field, value) {
647             (NameField::Authority, _) => TableIndex::FieldName(0),
648             (NameField::Path, "/") => TableIndex::Field(1),
649             (NameField::Path, _) => TableIndex::FieldName(1),
650             (NameField::Method, "CONNECT") => TableIndex::Field(15),
651             (NameField::Method, "DELETE") => TableIndex::Field(16),
652             (NameField::Method, "GET") => TableIndex::Field(17),
653             (NameField::Method, "HEAD") => TableIndex::Field(18),
654             (NameField::Method, "OPTIONS") => TableIndex::Field(19),
655             (NameField::Method, "POST") => TableIndex::Field(20),
656             (NameField::Method, "PUT") => TableIndex::Field(21),
657             (NameField::Method, _) => TableIndex::FieldName(15),
658             (NameField::Scheme, "http") => TableIndex::Field(22),
659             (NameField::Scheme, "https") => TableIndex::Field(23),
660             (NameField::Scheme, _) => TableIndex::FieldName(22),
661             (NameField::Status, "103") => TableIndex::Field(24),
662             (NameField::Status, "200") => TableIndex::Field(25),
663             (NameField::Status, "304") => TableIndex::Field(26),
664             (NameField::Status, "404") => TableIndex::Field(27),
665             (NameField::Status, "503") => TableIndex::Field(28),
666             (NameField::Status, "100") => TableIndex::Field(63),
667             (NameField::Status, "204") => TableIndex::Field(64),
668             (NameField::Status, "206") => TableIndex::Field(65),
669             (NameField::Status, "302") => TableIndex::Field(66),
670             (NameField::Status, "400") => TableIndex::Field(67),
671             (NameField::Status, "403") => TableIndex::Field(68),
672             (NameField::Status, "421") => TableIndex::Field(69),
673             (NameField::Status, "425") => TableIndex::Field(70),
674             (NameField::Status, "500") => TableIndex::Field(71),
675             (NameField::Status, _) => TableIndex::FieldName(24),
676             (NameField::Other(s), v) => match (s.as_str(), v) {
677                 ("age", "0") => TableIndex::Field(2),
678                 ("age", _) => TableIndex::FieldName(2),
679                 ("content-disposition", _) => TableIndex::FieldName(3),
680                 ("content-length", "0") => TableIndex::Field(4),
681                 ("content-length", _) => TableIndex::FieldName(4),
682                 ("cookie", _) => TableIndex::FieldName(5),
683                 ("date", _) => TableIndex::FieldName(6),
684                 ("etag", _) => TableIndex::FieldName(7),
685                 ("if-modified-since", _) => TableIndex::FieldName(8),
686                 ("if-none-match", _) => TableIndex::FieldName(9),
687                 ("last-modified", _) => TableIndex::FieldName(10),
688                 ("link", _) => TableIndex::FieldName(11),
689                 ("location", _) => TableIndex::FieldName(12),
690                 ("referer", _) => TableIndex::FieldName(13),
691                 ("set-cookie", _) => TableIndex::FieldName(14),
692                 ("accept", "*/*") => TableIndex::Field(29),
693                 ("accept", "application/dns-message") => TableIndex::Field(30),
694                 ("accept", _) => TableIndex::FieldName(29),
695                 ("accept-encoding", "gzip, deflate, br") => TableIndex::Field(31),
696                 ("accept-encoding", _) => TableIndex::FieldName(31),
697                 ("accept-ranges", "bytes") => TableIndex::Field(32),
698                 ("accept-ranges", _) => TableIndex::FieldName(32),
699                 ("access-control-allow-headers", "cache-control") => TableIndex::Field(33),
700                 ("access-control-allow-headers", "content-type") => TableIndex::Field(34),
701                 ("access-control-allow-origin", "*") => TableIndex::Field(35),
702                 ("access-control-allow-origin", _) => TableIndex::FieldName(35),
703                 ("cache-control", "max-age=0") => TableIndex::Field(36),
704                 ("cache-control", "max-age=2592000") => TableIndex::Field(37),
705                 ("cache-control", "max-age=604800") => TableIndex::Field(38),
706                 ("cache-control", "no-cache") => TableIndex::Field(39),
707                 ("cache-control", "no-store") => TableIndex::Field(40),
708                 ("cache-control", "public, max-age=31536000") => TableIndex::Field(41),
709                 ("cache-control", _) => TableIndex::FieldName(36),
710                 ("content-encoding", "br") => TableIndex::Field(42),
711                 ("content-encoding", "gzip") => TableIndex::Field(43),
712                 ("content-encoding", _) => TableIndex::FieldName(42),
713                 ("content-type", "application/dns-message") => TableIndex::Field(44),
714                 ("content-type", "application/javascript") => TableIndex::Field(45),
715                 ("content-type", "application/json") => TableIndex::Field(46),
716                 ("content-type", "application/x-www-form-urlencoded") => TableIndex::Field(47),
717                 ("content-type", "image/gif") => TableIndex::Field(48),
718                 ("content-type", "image/jpeg") => TableIndex::Field(49),
719                 ("content-type", "image/png") => TableIndex::Field(50),
720                 ("content-type", "text/css") => TableIndex::Field(51),
721                 ("content-type", "text/html; charset=utf-8") => TableIndex::Field(52),
722                 ("content-type", "text/plain") => TableIndex::Field(53),
723                 ("content-type", "text/plain;charset=utf-8") => TableIndex::Field(54),
724                 ("content-type", _) => TableIndex::FieldName(44),
725                 ("range", "bytes=0-") => TableIndex::Field(55),
726                 ("range", _) => TableIndex::FieldName(55),
727                 ("strict-transport-security", "max-age=31536000") => TableIndex::Field(56),
728                 ("strict-transport-security", "max-age=31536000; includesubdomains") => {
729                     TableIndex::Field(57)
730                 }
731                 ("strict-transport-security", "max-age=31536000; includesubdomains; preload") => {
732                     TableIndex::Field(58)
733                 }
734                 ("strict-transport-security", _) => TableIndex::FieldName(56),
735                 ("vary", "accept-encoding") => TableIndex::Field(59),
736                 ("vary", "origin") => TableIndex::Field(60),
737                 ("vary", _) => TableIndex::FieldName(59),
738                 ("x-content-type-options", "nosniff") => TableIndex::Field(61),
739                 ("x-content-type-options", _) => TableIndex::FieldName(61),
740                 ("x-xss-protection", "1; mode=block") => TableIndex::Field(62),
741                 ("x-xss-protection", _) => TableIndex::FieldName(62),
742                 ("accept-language", _) => TableIndex::FieldName(72),
743                 ("access-control-allow-credentials", "FALSE") => TableIndex::Field(73),
744                 ("access-control-allow-credentials", "TRUE") => TableIndex::Field(74),
745                 ("access-control-allow-credentials", _) => TableIndex::FieldName(73),
746                 ("access-control-allow-headers", "*") => TableIndex::Field(75),
747                 ("access-control-allow-headers", _) => TableIndex::FieldName(75),
748                 ("access-control-allow-methods", "get") => TableIndex::Field(76),
749                 ("access-control-allow-methods", "get, post, options") => TableIndex::Field(77),
750                 ("access-control-allow-methods", "options") => TableIndex::Field(78),
751                 ("access-control-allow-methods", _) => TableIndex::FieldName(76),
752                 ("access-control-expose-headers", "content-length") => TableIndex::Field(79),
753                 ("access-control-expose-headers", _) => TableIndex::FieldName(79),
754                 ("access-control-request-headers", "content-type") => TableIndex::Field(80),
755                 ("access-control-request-headers", _) => TableIndex::FieldName(80),
756                 ("access-control-request-method", "get") => TableIndex::Field(81),
757                 ("access-control-request-method", "post") => TableIndex::Field(82),
758                 ("access-control-request-method", _) => TableIndex::FieldName(81),
759                 ("alt-svc", "clear") => TableIndex::Field(83),
760                 ("alt-svc", _) => TableIndex::FieldName(83),
761                 ("authorization", _) => TableIndex::FieldName(84),
762                 (
763                     "content-security-policy",
764                     "script-src 'none'; object-src 'none'; base-uri 'none'",
765                 ) => TableIndex::Field(85),
766                 ("content-security-policy", _) => TableIndex::FieldName(85),
767                 ("early-data", "1") => TableIndex::Field(86),
768                 ("early-data", _) => TableIndex::FieldName(86),
769                 ("expect-ct", _) => TableIndex::FieldName(87),
770                 ("forwarded", _) => TableIndex::FieldName(88),
771                 ("if-range", _) => TableIndex::FieldName(89),
772                 ("origin", _) => TableIndex::FieldName(90),
773                 ("purpose", "prefetch") => TableIndex::Field(91),
774                 ("purpose", _) => TableIndex::FieldName(91),
775                 ("server", _) => TableIndex::FieldName(92),
776                 ("timing-allow-origin", "*") => TableIndex::Field(93),
777                 ("timing-allow-origin", _) => TableIndex::FieldName(93),
778                 ("upgrade-insecure-requests", "1") => TableIndex::Field(94),
779                 ("upgrade-insecure-requests", _) => TableIndex::FieldName(94),
780                 ("user-agent", _) => TableIndex::FieldName(95),
781                 ("x-forwarded-for", _) => TableIndex::FieldName(96),
782                 ("x-frame-options", "deny") => TableIndex::Field(97),
783                 ("x-frame-options", "sameorigin") => TableIndex::Field(98),
784                 ("x-frame-options", _) => TableIndex::FieldName(97),
785                 _ => TableIndex::None,
786             },
787         }
788     }
789 }
790 
791 #[derive(Clone, PartialEq, Eq, Debug)]
792 pub enum NameField {
793     Authority,
794     Method,
795     Path,
796     Scheme,
797     Status,
798     Other(String),
799 }
800 
801 impl NameField {
len(&self) -> usize802     pub(crate) fn len(&self) -> usize {
803         match self {
804             NameField::Authority => 10, // 10 is the length of ":authority".
805             NameField::Method => 7,     // 7 is the length of ":method".
806             NameField::Path => 5,       // 5 is the length of ":path".
807             NameField::Scheme => 7,     // 7 is the length of "scheme".
808             NameField::Status => 7,     // 7 is the length of "status".
809             NameField::Other(s) => s.len(),
810         }
811     }
812 }
813 
814 impl ToString for NameField {
to_string(&self) -> String815     fn to_string(&self) -> String {
816         match self {
817             NameField::Authority => String::from(":authority"),
818             NameField::Method => String::from(":method"),
819             NameField::Path => String::from(":path"),
820             NameField::Scheme => String::from(":scheme"),
821             NameField::Status => String::from(":status"),
822             NameField::Other(s) => s.clone(),
823         }
824     }
825 }
826