68 lines
1.9 KiB
Rust
68 lines
1.9 KiB
Rust
use crate::header::{Entry, HeaderMap, OccupiedEntry};
|
|
|
|
// xor-shift
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
pub(crate) fn fast_random() -> u64 {
|
|
use std::cell::Cell;
|
|
use std::collections::hash_map::RandomState;
|
|
use std::hash::{BuildHasher, Hasher};
|
|
use std::num::Wrapping;
|
|
|
|
thread_local! {
|
|
static RNG: Cell<Wrapping<u64>> = Cell::new(Wrapping(seed()));
|
|
}
|
|
|
|
fn seed() -> u64 {
|
|
let seed = RandomState::new();
|
|
|
|
let mut out = 0;
|
|
let mut cnt = 0;
|
|
while out == 0 {
|
|
cnt += 1;
|
|
let mut hasher = seed.build_hasher();
|
|
hasher.write_usize(cnt);
|
|
out = hasher.finish();
|
|
}
|
|
out
|
|
}
|
|
|
|
RNG.with(|rng| {
|
|
let mut n = rng.get();
|
|
debug_assert_ne!(n.0, 0);
|
|
n ^= n >> 12;
|
|
n ^= n << 25;
|
|
n ^= n >> 27;
|
|
rng.set(n);
|
|
n.0.wrapping_mul(0x2545_f491_4f6c_dd1d)
|
|
})
|
|
}
|
|
|
|
pub(crate) fn replace_headers(dst: &mut HeaderMap, src: HeaderMap) {
|
|
// IntoIter of HeaderMap yields (Option<HeaderName>, HeaderValue).
|
|
// The first time a name is yielded, it will be Some(name), and if
|
|
// there are more values with the same name, the next yield will be
|
|
// None.
|
|
|
|
let mut prev_entry: Option<OccupiedEntry<_>> = None;
|
|
for (key, value) in src {
|
|
match key {
|
|
Some(key) => match dst.entry(key) {
|
|
Entry::Occupied(mut e) => {
|
|
e.insert(value);
|
|
prev_entry = Some(e);
|
|
}
|
|
Entry::Vacant(e) => {
|
|
let e = e.insert_entry(value);
|
|
prev_entry = Some(e);
|
|
}
|
|
},
|
|
None => match prev_entry {
|
|
Some(ref mut entry) => {
|
|
entry.append(value);
|
|
}
|
|
None => unreachable!("HeaderMap::into_iter yielded None first"),
|
|
},
|
|
}
|
|
}
|
|
}
|