leyline-http 0.1.5

HTTP client that impersonates Chrome, Firefox, and Safari on the wire: TLS (JA3/JA4), HTTP/2, and HTTP/3 fingerprints
Documentation
use std::collections::HashMap;
use std::hash::{BuildHasherDefault, Hasher};
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};

use super::StreamActor;

pub(super) struct StreamMap {
    inner: HashMap<u32, StreamActor, BuildHasherDefault<StreamIdHasher>>,
    open: Arc<AtomicUsize>,
}

#[derive(Default)]
struct StreamIdHasher(u64);

impl Hasher for StreamIdHasher {
    fn write(&mut self, bytes: &[u8]) {
        for &b in bytes {
            self.write_u32(b as u32);
        }
    }

    fn write_u32(&mut self, n: u32) {
        self.0 = (n as u64).wrapping_mul(0x9E37_79B9_7F4A_7C15);
    }

    fn write_usize(&mut self, n: usize) {
        self.0 = (n as u64).wrapping_mul(0x9E37_79B9_7F4A_7C15);
    }

    fn finish(&self) -> u64 {
        self.0 >> 33
    }
}

impl StreamMap {
    pub(super) fn new(open: Arc<AtomicUsize>) -> Self {
        Self {
            inner: HashMap::default(),
            open,
        }
    }

    fn publish(&self) {
        self.open.store(self.inner.len(), Ordering::Relaxed);
    }

    pub(super) fn get(&self, stream_id: u32) -> Option<&StreamActor> {
        self.inner.get(&stream_id)
    }

    pub(super) fn get_mut(&mut self, stream_id: u32) -> Option<&mut StreamActor> {
        self.inner.get_mut(&stream_id)
    }

    pub(super) fn insert(&mut self, stream_id: u32, actor: StreamActor) {
        self.inner.insert(stream_id, actor);
        self.publish();
    }

    pub(super) fn remove(&mut self, stream_id: u32) -> Option<StreamActor> {
        let actor = self.inner.remove(&stream_id);
        self.publish();
        actor
    }

    pub(super) fn iter(&self) -> impl Iterator<Item = (u32, &StreamActor)> {
        self.inner.iter().map(|(&id, actor)| (id, actor))
    }

    pub(super) fn keys(&self) -> impl Iterator<Item = &u32> {
        self.inner.keys()
    }

    pub(super) fn iter_mut(&mut self) -> impl Iterator<Item = (u32, &mut StreamActor)> {
        self.inner.iter_mut().map(|(&id, actor)| (id, actor))
    }

    pub(super) fn drain(&mut self) -> impl Iterator<Item = (u32, StreamActor)> {
        self.open.store(0, Ordering::Relaxed);
        self.inner.drain()
    }

    pub(super) fn values(&self) -> impl Iterator<Item = &StreamActor> {
        self.inner.values()
    }

    pub(super) fn len(&self) -> usize {
        self.inner.len()
    }

    pub(super) fn is_empty(&self) -> bool {
        self.inner.is_empty()
    }
}