neco-server-router 0.1.0

fixed-path router primitives for neco-server
Documentation
use std::any::{Any, TypeId};
use std::collections::HashMap;

/// Request-local typed extensions for router and middleware context.
#[derive(Default)]
pub struct Extensions {
    entries: HashMap<TypeId, Box<dyn Any + Send + Sync>>,
}

impl Extensions {
    /// Creates an empty extensions map.
    pub fn new() -> Self {
        Self::default()
    }

    /// Inserts a typed value, replacing any previous value of the same type.
    pub fn insert<T>(&mut self, value: T) -> Option<T>
    where
        T: Any + Send + Sync + 'static,
    {
        self.entries
            .insert(TypeId::of::<T>(), Box::new(value))
            .and_then(|value| value.downcast::<T>().ok())
            .map(|value| *value)
    }

    /// Returns a shared reference to a previously inserted typed value.
    pub fn get<T>(&self) -> Option<&T>
    where
        T: Any + Send + Sync + 'static,
    {
        self.entries
            .get(&TypeId::of::<T>())
            .and_then(|value| value.downcast_ref::<T>())
    }

    /// Returns a mutable reference to a previously inserted typed value.
    pub fn get_mut<T>(&mut self) -> Option<&mut T>
    where
        T: Any + Send + Sync + 'static,
    {
        self.entries
            .get_mut(&TypeId::of::<T>())
            .and_then(|value| value.downcast_mut::<T>())
    }

    /// Removes a previously inserted typed value.
    pub fn remove<T>(&mut self) -> Option<T>
    where
        T: Any + Send + Sync + 'static,
    {
        self.entries
            .remove(&TypeId::of::<T>())
            .and_then(|value| value.downcast::<T>().ok())
            .map(|value| *value)
    }
}

#[cfg(test)]
mod tests {
    use super::Extensions;

    #[test]
    fn extensions_store_typed_values() {
        let mut extensions = Extensions::new();
        assert_eq!(extensions.insert::<u64>(7), None);
        assert_eq!(extensions.get::<u64>(), Some(&7));
        assert_eq!(extensions.remove::<u64>(), Some(7));
        assert_eq!(extensions.get::<u64>(), None);
    }
}