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