1 | use crate::header::{Entry, HeaderMap, HeaderValue, OccupiedEntry}; |
2 | |
3 | pub fn basic_auth<U, P>(username: U, password: Option<P>) -> HeaderValue |
4 | where |
5 | U: std::fmt::Display, |
6 | P: std::fmt::Display, |
7 | { |
8 | use base64::prelude::BASE64_STANDARD; |
9 | use base64::write::EncoderWriter; |
10 | use std::io::Write; |
11 | |
12 | let mut buf: Vec = b"Basic " .to_vec(); |
13 | { |
14 | let mut encoder: EncoderWriter<'_, GeneralPurpose, …> = EncoderWriter::new(&mut buf, &BASE64_STANDARD); |
15 | let _ = write!(encoder, " {username}:" ); |
16 | if let Some(password: P) = password { |
17 | let _ = write!(encoder, " {password}" ); |
18 | } |
19 | } |
20 | let mut header: HeaderValue = HeaderValue::from_bytes(&buf).expect(msg:"base64 is always valid HeaderValue" ); |
21 | header.set_sensitive(val:true); |
22 | header |
23 | } |
24 | |
25 | // xor-shift |
26 | #[cfg (not(target_arch = "wasm32" ))] |
27 | pub(crate) fn fast_random() -> u64 { |
28 | use std::cell::Cell; |
29 | use std::collections::hash_map::RandomState; |
30 | use std::hash::{BuildHasher, Hasher}; |
31 | use std::num::Wrapping; |
32 | |
33 | thread_local! { |
34 | static RNG: Cell<Wrapping<u64>> = Cell::new(Wrapping(seed())); |
35 | } |
36 | |
37 | fn seed() -> u64 { |
38 | let seed = RandomState::new(); |
39 | |
40 | let mut out = 0; |
41 | let mut cnt = 0; |
42 | while out == 0 { |
43 | cnt += 1; |
44 | let mut hasher = seed.build_hasher(); |
45 | hasher.write_usize(cnt); |
46 | out = hasher.finish(); |
47 | } |
48 | out |
49 | } |
50 | |
51 | RNG.with(|rng| { |
52 | let mut n = rng.get(); |
53 | debug_assert_ne!(n.0, 0); |
54 | n ^= n >> 12; |
55 | n ^= n << 25; |
56 | n ^= n >> 27; |
57 | rng.set(n); |
58 | n.0.wrapping_mul(0x2545_f491_4f6c_dd1d) |
59 | }) |
60 | } |
61 | |
62 | pub(crate) fn replace_headers(dst: &mut HeaderMap, src: HeaderMap) { |
63 | // IntoIter of HeaderMap yields (Option<HeaderName>, HeaderValue). |
64 | // The first time a name is yielded, it will be Some(name), and if |
65 | // there are more values with the same name, the next yield will be |
66 | // None. |
67 | |
68 | let mut prev_entry: Option<OccupiedEntry<_>> = None; |
69 | for (key, value) in src { |
70 | match key { |
71 | Some(key) => match dst.entry(key) { |
72 | Entry::Occupied(mut e) => { |
73 | e.insert(value); |
74 | prev_entry = Some(e); |
75 | } |
76 | Entry::Vacant(e) => { |
77 | let e = e.insert_entry(value); |
78 | prev_entry = Some(e); |
79 | } |
80 | }, |
81 | None => match prev_entry { |
82 | Some(ref mut entry) => { |
83 | entry.append(value); |
84 | } |
85 | None => unreachable!("HeaderMap::into_iter yielded None first" ), |
86 | }, |
87 | } |
88 | } |
89 | } |
90 | |