1use super::Header;
2
3use fnv::FnvHasher;
4use http::header;
5use http::method::Method;
6
7use std::collections::VecDeque;
8use std::hash::{Hash, Hasher};
9use std::{cmp, mem, usize};
10
11#[derive(Debug)]
13pub struct Table {
14 mask: usize,
15 indices: Vec<Option<Pos>>,
16 slots: VecDeque<Slot>,
17 inserted: usize,
18 size: usize,
20 max_size: usize,
21}
22
23#[derive(Debug)]
24pub enum Index {
25 Indexed(usize, Header),
27
28 Name(usize, Header),
30
31 Inserted(usize),
33
34 InsertedValue(usize, usize),
36
37 NotIndexed(Header),
39}
40
41#[derive(Debug)]
42struct Slot {
43 hash: HashValue,
44 header: Header,
45 next: Option<usize>,
46}
47
48#[derive(Debug, Clone, Copy, Eq, PartialEq)]
49struct Pos {
50 index: usize,
51 hash: HashValue,
52}
53
54#[derive(Debug, Copy, Clone, Eq, PartialEq)]
55struct HashValue(usize);
56
57const MAX_SIZE: usize = 1 << 16;
58const DYN_OFFSET: usize = 62;
59
60macro_rules! probe_loop {
61 ($probe_var: ident < $len: expr, $body: expr) => {
62 debug_assert!($len > 0);
63 loop {
64 if $probe_var < $len {
65 $body
66 $probe_var += 1;
67 } else {
68 $probe_var = 0;
69 }
70 }
71 };
72}
73
74impl Table {
75 pub fn new(max_size: usize, capacity: usize) -> Table {
76 if capacity == 0 {
77 Table {
78 mask: 0,
79 indices: vec![],
80 slots: VecDeque::new(),
81 inserted: 0,
82 size: 0,
83 max_size,
84 }
85 } else {
86 let capacity = cmp::max(to_raw_capacity(capacity).next_power_of_two(), 8);
87
88 Table {
89 mask: capacity.wrapping_sub(1),
90 indices: vec![None; capacity],
91 slots: VecDeque::with_capacity(usable_capacity(capacity)),
92 inserted: 0,
93 size: 0,
94 max_size,
95 }
96 }
97 }
98
99 #[inline]
100 pub fn capacity(&self) -> usize {
101 usable_capacity(self.indices.len())
102 }
103
104 pub fn max_size(&self) -> usize {
105 self.max_size
106 }
107
108 pub fn resolve<'a>(&'a self, index: &'a Index) -> &'a Header {
110 use self::Index::*;
111
112 match *index {
113 Indexed(_, ref h) => h,
114 Name(_, ref h) => h,
115 Inserted(idx) => &self.slots[idx].header,
116 InsertedValue(_, idx) => &self.slots[idx].header,
117 NotIndexed(ref h) => h,
118 }
119 }
120
121 pub fn resolve_idx(&self, index: &Index) -> usize {
122 use self::Index::*;
123
124 match *index {
125 Indexed(idx, ..) => idx,
126 Name(idx, ..) => idx,
127 Inserted(idx) => idx + DYN_OFFSET,
128 InsertedValue(_name_idx, slot_idx) => slot_idx + DYN_OFFSET,
129 NotIndexed(_) => panic!("cannot resolve index"),
130 }
131 }
132
133 pub fn index(&mut self, header: Header) -> Index {
135 let statik = index_static(&header);
137
138 if header.skip_value_index() {
140 debug_assert!(statik.is_some(), "skip_value_index requires a static name",);
144 return Index::new(statik, header);
145 }
146
147 if let Some((n, true)) = statik {
149 return Index::Indexed(n, header);
150 }
151
152 if header.len() * 4 > self.max_size * 3 {
154 return Index::new(statik, header);
155 }
156
157 self.index_dynamic(header, statik)
158 }
159
160 fn index_dynamic(&mut self, header: Header, statik: Option<(usize, bool)>) -> Index {
161 debug_assert!(self.assert_valid_state("one"));
162
163 if header.len() + self.size < self.max_size || !header.is_sensitive() {
164 self.reserve_one();
166 }
167
168 if self.indices.is_empty() {
169 return Index::new(statik, header);
173 }
174
175 let hash = hash_header(&header);
176
177 let desired_pos = desired_pos(self.mask, hash);
178 let mut probe = desired_pos;
179 let mut dist = 0;
180
181 probe_loop!(probe < self.indices.len(), {
183 if let Some(pos) = self.indices[probe] {
184 let their_dist = probe_distance(self.mask, pos.hash, probe);
187
188 let slot_idx = pos.index.wrapping_add(self.inserted);
189
190 if their_dist < dist {
191 return self.index_vacant(header, hash, dist, probe, statik);
193 } else if pos.hash == hash && self.slots[slot_idx].header.name() == header.name() {
194 return self.index_occupied(header, hash, pos.index, statik.map(|(n, _)| n));
196 }
197 } else {
198 return self.index_vacant(header, hash, dist, probe, statik);
199 }
200
201 dist += 1;
202 });
203 }
204
205 fn index_occupied(
206 &mut self,
207 header: Header,
208 hash: HashValue,
209 mut index: usize,
210 statik: Option<usize>,
211 ) -> Index {
212 debug_assert!(self.assert_valid_state("top"));
213
214 loop {
218 let real_idx = index.wrapping_add(self.inserted);
220
221 if self.slots[real_idx].header.value_eq(&header) {
222 return Index::Indexed(real_idx + DYN_OFFSET, header);
224 }
225
226 if let Some(next) = self.slots[real_idx].next {
227 index = next;
228 continue;
229 }
230
231 if header.is_sensitive() {
232 return Index::Name(real_idx + DYN_OFFSET, header);
235 }
236
237 self.update_size(header.len(), Some(index));
238
239 self.insert(header, hash);
241
242 let new_real_idx = index.wrapping_add(self.inserted);
244
245 if new_real_idx < self.slots.len() {
248 let idx = 0usize.wrapping_sub(self.inserted);
249
250 self.slots[new_real_idx].next = Some(idx);
251 }
252
253 debug_assert!(self.assert_valid_state("bottom"));
254
255 return if let Some(n) = statik {
258 Index::InsertedValue(n, 0)
260 } else {
261 Index::InsertedValue(real_idx + DYN_OFFSET, 0)
262 };
263 }
264 }
265
266 fn index_vacant(
267 &mut self,
268 header: Header,
269 hash: HashValue,
270 mut dist: usize,
271 mut probe: usize,
272 statik: Option<(usize, bool)>,
273 ) -> Index {
274 if header.is_sensitive() {
275 return Index::new(statik, header);
276 }
277
278 debug_assert!(self.assert_valid_state("top"));
279 debug_assert!(dist == 0 || self.indices[probe.wrapping_sub(1) & self.mask].is_some());
280
281 if self.update_size(header.len(), None) {
284 while dist != 0 {
285 let back = probe.wrapping_sub(1) & self.mask;
286
287 if let Some(pos) = self.indices[back] {
288 let their_dist = probe_distance(self.mask, pos.hash, back);
289
290 if their_dist < (dist - 1) {
291 probe = back;
292 dist -= 1;
293 } else {
294 break;
295 }
296 } else {
297 probe = back;
298 dist -= 1;
299 }
300 }
301 }
302
303 debug_assert!(self.assert_valid_state("after update"));
304
305 self.insert(header, hash);
306
307 let pos_idx = 0usize.wrapping_sub(self.inserted);
308
309 let prev = mem::replace(
310 &mut self.indices[probe],
311 Some(Pos {
312 index: pos_idx,
313 hash,
314 }),
315 );
316
317 if let Some(mut prev) = prev {
318 let mut probe = probe + 1;
320
321 probe_loop!(probe < self.indices.len(), {
322 let pos = &mut self.indices[probe];
323
324 prev = match mem::replace(pos, Some(prev)) {
325 Some(p) => p,
326 None => break,
327 };
328 });
329 }
330
331 debug_assert!(self.assert_valid_state("bottom"));
332
333 if let Some((n, _)) = statik {
334 Index::InsertedValue(n, 0)
335 } else {
336 Index::Inserted(0)
337 }
338 }
339
340 fn insert(&mut self, header: Header, hash: HashValue) {
341 self.inserted = self.inserted.wrapping_add(1);
342
343 self.slots.push_front(Slot {
344 hash,
345 header,
346 next: None,
347 });
348 }
349
350 pub fn resize(&mut self, size: usize) {
351 self.max_size = size;
352
353 if size == 0 {
354 self.size = 0;
355
356 for i in &mut self.indices {
357 *i = None;
358 }
359
360 self.slots.clear();
361 self.inserted = 0;
362 } else {
363 self.converge(None);
364 }
365 }
366
367 fn update_size(&mut self, len: usize, prev_idx: Option<usize>) -> bool {
368 self.size += len;
369 self.converge(prev_idx)
370 }
371
372 fn converge(&mut self, prev_idx: Option<usize>) -> bool {
373 let mut ret = false;
374
375 while self.size > self.max_size {
376 ret = true;
377 self.evict(prev_idx);
378 }
379
380 ret
381 }
382
383 fn evict(&mut self, prev_idx: Option<usize>) {
384 let pos_idx = (self.slots.len() - 1).wrapping_sub(self.inserted);
385
386 debug_assert!(!self.slots.is_empty());
387 debug_assert!(self.assert_valid_state("one"));
388
389 let slot = self.slots.pop_back().unwrap();
391 let mut probe = desired_pos(self.mask, slot.hash);
392
393 self.size -= slot.header.len();
395
396 debug_assert_eq!(
397 self.indices
398 .iter()
399 .filter_map(|p| *p)
400 .filter(|p| p.index == pos_idx)
401 .count(),
402 1
403 );
404
405 probe_loop!(probe < self.indices.len(), {
407 debug_assert!(self.indices[probe].is_some());
408
409 let mut pos = self.indices[probe].unwrap();
410
411 if pos.index == pos_idx {
412 if let Some(idx) = slot.next {
413 pos.index = idx;
414 self.indices[probe] = Some(pos);
415 } else if Some(pos.index) == prev_idx {
416 pos.index = 0usize.wrapping_sub(self.inserted + 1);
417 self.indices[probe] = Some(pos);
418 } else {
419 self.indices[probe] = None;
420 self.remove_phase_two(probe);
421 }
422
423 break;
424 }
425 });
426
427 debug_assert!(self.assert_valid_state("two"));
428 }
429
430 fn remove_phase_two(&mut self, probe: usize) {
433 let mut last_probe = probe;
434 let mut probe = probe + 1;
435
436 probe_loop!(probe < self.indices.len(), {
437 if let Some(pos) = self.indices[probe] {
438 if probe_distance(self.mask, pos.hash, probe) > 0 {
439 self.indices[last_probe] = self.indices[probe].take();
440 } else {
441 break;
442 }
443 } else {
444 break;
445 }
446
447 last_probe = probe;
448 });
449
450 debug_assert!(self.assert_valid_state("two"));
451 }
452
453 fn reserve_one(&mut self) {
454 let len = self.slots.len();
455
456 if len == self.capacity() {
457 if len == 0 {
458 let new_raw_cap = 8;
459 self.mask = 8 - 1;
460 self.indices = vec![None; new_raw_cap];
461 } else {
462 let raw_cap = self.indices.len();
463 self.grow(raw_cap << 1);
464 }
465 }
466 }
467
468 #[inline]
469 fn grow(&mut self, new_raw_cap: usize) {
470 debug_assert!(self.assert_valid_state("top"));
474
475 let mut first_ideal = 0;
477
478 for (i, pos) in self.indices.iter().enumerate() {
479 if let Some(pos) = *pos {
480 if 0 == probe_distance(self.mask, pos.hash, i) {
481 first_ideal = i;
482 break;
483 }
484 }
485 }
486
487 let old_indices = mem::replace(&mut self.indices, vec![None; new_raw_cap]);
490 self.mask = new_raw_cap.wrapping_sub(1);
491
492 for &pos in &old_indices[first_ideal..] {
493 self.reinsert_entry_in_order(pos);
494 }
495
496 for &pos in &old_indices[..first_ideal] {
497 self.reinsert_entry_in_order(pos);
498 }
499
500 debug_assert!(self.assert_valid_state("bottom"));
501 }
502
503 fn reinsert_entry_in_order(&mut self, pos: Option<Pos>) {
504 if let Some(pos) = pos {
505 let mut probe = desired_pos(self.mask, pos.hash);
507
508 probe_loop!(probe < self.indices.len(), {
509 if self.indices[probe].is_none() {
510 self.indices[probe] = Some(pos);
512 return;
513 }
514
515 debug_assert!({
516 let them = self.indices[probe].unwrap();
517 let their_distance = probe_distance(self.mask, them.hash, probe);
518 let our_distance = probe_distance(self.mask, pos.hash, probe);
519
520 their_distance >= our_distance
521 });
522 });
523 }
524 }
525
526 #[cfg(not(test))]
527 fn assert_valid_state(&self, _: &'static str) -> bool {
528 true
529 }
530
531 #[cfg(test)]
532 fn assert_valid_state(&self, _msg: &'static str) -> bool {
533 true
621 }
622}
623
624#[cfg(test)]
625impl Table {
626 pub fn len(&self) -> usize {
628 self.slots.len()
629 }
630
631 pub fn size(&self) -> usize {
633 self.size
634 }
635}
636
637impl Index {
638 fn new(v: Option<(usize, bool)>, e: Header) -> Index {
639 match v {
640 None => Index::NotIndexed(e),
641 Some((n, true)) => Index::Indexed(n, e),
642 Some((n, false)) => Index::Name(n, e),
643 }
644 }
645}
646
647#[inline]
648fn usable_capacity(cap: usize) -> usize {
649 cap - cap / 4
650}
651
652#[inline]
653fn to_raw_capacity(n: usize) -> usize {
654 n + n / 3
655}
656
657#[inline]
658fn desired_pos(mask: usize, hash: HashValue) -> usize {
659 hash.0 & mask
660}
661
662#[inline]
663fn probe_distance(mask: usize, hash: HashValue, current: usize) -> usize {
664 current.wrapping_sub(desired_pos(mask, hash)) & mask
665}
666
667fn hash_header(header: &Header) -> HashValue {
668 const MASK: u64 = (MAX_SIZE as u64) - 1;
669
670 let mut h = FnvHasher::default();
671 header.name().hash(&mut h);
672 HashValue((h.finish() & MASK) as usize)
673}
674
675fn index_static(header: &Header) -> Option<(usize, bool)> {
678 match *header {
679 Header::Field {
680 ref name,
681 ref value,
682 } => match *name {
683 header::ACCEPT_CHARSET => Some((15, false)),
684 header::ACCEPT_ENCODING => {
685 if value == "gzip, deflate" {
686 Some((16, true))
687 } else {
688 Some((16, false))
689 }
690 }
691 header::ACCEPT_LANGUAGE => Some((17, false)),
692 header::ACCEPT_RANGES => Some((18, false)),
693 header::ACCEPT => Some((19, false)),
694 header::ACCESS_CONTROL_ALLOW_ORIGIN => Some((20, false)),
695 header::AGE => Some((21, false)),
696 header::ALLOW => Some((22, false)),
697 header::AUTHORIZATION => Some((23, false)),
698 header::CACHE_CONTROL => Some((24, false)),
699 header::CONTENT_DISPOSITION => Some((25, false)),
700 header::CONTENT_ENCODING => Some((26, false)),
701 header::CONTENT_LANGUAGE => Some((27, false)),
702 header::CONTENT_LENGTH => Some((28, false)),
703 header::CONTENT_LOCATION => Some((29, false)),
704 header::CONTENT_RANGE => Some((30, false)),
705 header::CONTENT_TYPE => Some((31, false)),
706 header::COOKIE => Some((32, false)),
707 header::DATE => Some((33, false)),
708 header::ETAG => Some((34, false)),
709 header::EXPECT => Some((35, false)),
710 header::EXPIRES => Some((36, false)),
711 header::FROM => Some((37, false)),
712 header::HOST => Some((38, false)),
713 header::IF_MATCH => Some((39, false)),
714 header::IF_MODIFIED_SINCE => Some((40, false)),
715 header::IF_NONE_MATCH => Some((41, false)),
716 header::IF_RANGE => Some((42, false)),
717 header::IF_UNMODIFIED_SINCE => Some((43, false)),
718 header::LAST_MODIFIED => Some((44, false)),
719 header::LINK => Some((45, false)),
720 header::LOCATION => Some((46, false)),
721 header::MAX_FORWARDS => Some((47, false)),
722 header::PROXY_AUTHENTICATE => Some((48, false)),
723 header::PROXY_AUTHORIZATION => Some((49, false)),
724 header::RANGE => Some((50, false)),
725 header::REFERER => Some((51, false)),
726 header::REFRESH => Some((52, false)),
727 header::RETRY_AFTER => Some((53, false)),
728 header::SERVER => Some((54, false)),
729 header::SET_COOKIE => Some((55, false)),
730 header::STRICT_TRANSPORT_SECURITY => Some((56, false)),
731 header::TRANSFER_ENCODING => Some((57, false)),
732 header::USER_AGENT => Some((58, false)),
733 header::VARY => Some((59, false)),
734 header::VIA => Some((60, false)),
735 header::WWW_AUTHENTICATE => Some((61, false)),
736 _ => None,
737 },
738 Header::Authority(_) => Some((1, false)),
739 Header::Method(ref v) => match *v {
740 Method::GET => Some((2, true)),
741 Method::POST => Some((3, true)),
742 _ => Some((2, false)),
743 },
744 Header::Scheme(ref v) => match &**v {
745 "http" => Some((6, true)),
746 "https" => Some((7, true)),
747 _ => Some((6, false)),
748 },
749 Header::Path(ref v) => match &**v {
750 "/" => Some((4, true)),
751 "/index.html" => Some((5, true)),
752 _ => Some((4, false)),
753 },
754 Header::Protocol(..) => None,
755 Header::Status(ref v) => match u16::from(*v) {
756 200 => Some((8, true)),
757 204 => Some((9, true)),
758 206 => Some((10, true)),
759 304 => Some((11, true)),
760 400 => Some((12, true)),
761 404 => Some((13, true)),
762 500 => Some((14, true)),
763 _ => Some((8, false)),
764 },
765 }
766}