1 use crate::header::HeaderMap;
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 // TODO: a complex exercise would be to optimize this to only
47 // require 1 hash/lookup of the key, but doing something fancy
48 // with header::Entry...
49
50 let mut prev_name = None;
51 for (key, value) in src {
52 match key {
53 Some(key) => {
54 dst.insert(key.clone(), value);
55 prev_name = Some(key);
56 }
57 None => match prev_name {
58 Some(ref key) => {
59 dst.append(key.clone(), value);
60 }
61 None => unreachable!("HeaderMap::into_iter yielded None first"),
62 },
63 }
64 }
65 }
66