1 use crate::header::{Entry, HeaderMap, OccupiedEntry};
2
3 // xor-shift
4 #[cfg(not(target_arch = "wasm32"))]
fast_random() -> u645 pub(crate) fn fast_random() -> u64 {
6 use std::cell::Cell;
7 use std::collections::hash_map::RandomState;
8 use std::hash::{BuildHasher, Hasher};
9 use std::num::Wrapping;
10
11 thread_local! {
12 static RNG: Cell<Wrapping<u64>> = Cell::new(Wrapping(seed()));
13 }
14
15 fn seed() -> u64 {
16 let seed = RandomState::new();
17
18 let mut out = 0;
19 let mut cnt = 0;
20 while out == 0 {
21 cnt += 1;
22 let mut hasher = seed.build_hasher();
23 hasher.write_usize(cnt);
24 out = hasher.finish();
25 }
26 out
27 }
28
29 RNG.with(|rng| {
30 let mut n = rng.get();
31 debug_assert_ne!(n.0, 0);
32 n ^= n >> 12;
33 n ^= n << 25;
34 n ^= n >> 27;
35 rng.set(n);
36 n.0.wrapping_mul(0x2545_f491_4f6c_dd1d)
37 })
38 }
39
replace_headers(dst: &mut HeaderMap, src: HeaderMap)40 pub(crate) fn replace_headers(dst: &mut HeaderMap, src: HeaderMap) {
41 // IntoIter of HeaderMap yields (Option<HeaderName>, HeaderValue).
42 // The first time a name is yielded, it will be Some(name), and if
43 // there are more values with the same name, the next yield will be
44 // None.
45
46 let mut prev_entry: Option<OccupiedEntry<_>> = None;
47 for (key, value) in src {
48 match key {
49 Some(key) => match dst.entry(key) {
50 Entry::Occupied(mut e) => {
51 e.insert(value);
52 prev_entry = Some(e);
53 }
54 Entry::Vacant(e) => {
55 let e = e.insert_entry(value);
56 prev_entry = Some(e);
57 }
58 },
59 None => match prev_entry {
60 Some(ref mut entry) => {
61 entry.append(value);
62 }
63 None => unreachable!("HeaderMap::into_iter yielded None first"),
64 },
65 }
66 }
67 }
68