reqwest/
util.rs

1use crate::header::{Entry, HeaderMap, HeaderValue, OccupiedEntry};
2
3pub fn basic_auth<U, P>(username: U, password: Option<P>) -> HeaderValue
4where
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 = b"Basic ".to_vec();
13    {
14        let mut encoder = EncoderWriter::new(&mut buf, &BASE64_STANDARD);
15        let _ = write!(encoder, "{username}:");
16        if let Some(password) = password {
17            let _ = write!(encoder, "{password}");
18        }
19    }
20    let mut header = HeaderValue::from_bytes(&buf).expect("base64 is always valid HeaderValue");
21    header.set_sensitive(true);
22    header
23}
24
25// xor-shift
26#[cfg(not(target_arch = "wasm32"))]
27pub(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
62pub(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}