use std::any::{Any, TypeId};
use std::collections::HashMap;
#[derive(Default)]
pub struct Extensions {
entries: HashMap<TypeId, Box<dyn Any + Send + Sync>>,
}
impl Extensions {
pub fn new() -> Self {
Self::default()
}
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)
}
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>())
}
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>())
}
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);
}
}