use parking_lot::RwLock; use std::any::{type_name, Any}; use std::collections::HashMap; use std::fmt::Debug; use std::hash::Hash; use std::sync::Arc; #[derive(Default, Debug)] /// The better option is use LRU cache pub struct AnyTypeCache(HashMap); impl AnyTypeCache where TypeValueKey: Clone + Hash + Eq, { pub fn new() -> Arc>> { Arc::new(RwLock::new(AnyTypeCache(HashMap::default()))) } pub fn insert(&mut self, key: &TypeValueKey, val: T) -> Option where T: 'static + Send + Sync, { self .0 .insert(key.clone(), TypeValue::new(val)) .and_then(downcast_owned) } pub fn remove(&mut self, key: &TypeValueKey) { self.0.remove(key); } pub fn get(&self, key: &TypeValueKey) -> Option<&T> where T: 'static + Send + Sync, { self .0 .get(key) .and_then(|type_value| type_value.boxed.downcast_ref()) } pub fn get_mut(&mut self, key: &TypeValueKey) -> Option<&mut T> where T: 'static + Send + Sync, { self .0 .get_mut(key) .and_then(|type_value| type_value.boxed.downcast_mut()) } pub fn contains(&self, key: &TypeValueKey) -> bool { self.0.contains_key(key) } pub fn is_empty(&self) -> bool { self.0.is_empty() } } fn downcast_owned(type_value: TypeValue) -> Option { type_value.boxed.downcast().ok().map(|boxed| *boxed) } #[derive(Debug)] struct TypeValue { boxed: Box, #[allow(dead_code)] ty: &'static str, } impl TypeValue { pub fn new(value: T) -> Self where T: Send + Sync + 'static, { Self { boxed: Box::new(value), ty: type_name::(), } } } impl std::ops::Deref for TypeValue { type Target = Box; fn deref(&self) -> &Self::Target { &self.boxed } } impl std::ops::DerefMut for TypeValue { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.boxed } }