| 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 | |