foxhole 0.4.0

A Blazingly-fast http framework
Documentation
use std::{
    any::{Any, TypeId},
    collections::HashMap,
};

type Value = Box<dyn Any + Sync + Send>;

/// This trait allows a type to be used as a key in a `TypeCache`
pub trait TypeCacheKey: 'static {
    type Value: Send + Sync;
}

#[derive(Default)]
pub struct TypeCache {
    inner: HashMap<TypeId, Value>,
}

impl TypeCache {
    pub fn new() -> Self {
        Self {
            inner: HashMap::new(),
        }
    }

    pub fn get<K: TypeCacheKey>(&self) -> Option<&K::Value> {
        self.inner
            .get(&TypeId::of::<K>())
            .map(|f| f.downcast_ref().unwrap())
    }

    pub fn insert<K: TypeCacheKey>(&mut self, value: K::Value) -> Option<Box<K::Value>> {
        self.inner
            .insert(TypeId::of::<K>(), Box::new(value))
            .map(|f| f.downcast().unwrap())
    }

    pub fn remove<K: TypeCacheKey>(&mut self) -> Option<Box<K::Value>> {
        self.inner
            .remove(&TypeId::of::<K>())
            .map(|f| f.downcast().unwrap())
    }
}

#[cfg(test)]
mod tests {
    use std::sync::Arc;

    use super::*;

    pub struct UserId;

    impl TypeCacheKey for UserId {
        type Value = Arc<u32>;
    }

    #[test]
    fn type_map() {
        let mut cache = TypeCache::new();

        assert!(cache.insert::<UserId>(Arc::new(0)).is_none());

        assert!(cache.get::<UserId>().is_some());

        assert!(cache.insert::<UserId>(Arc::new(0)).is_some());

        assert!(cache.remove::<UserId>().is_some());
    }
}