use {
std::{
any::{Any, TypeId},
collections::HashMap,
sync::Arc,
},
tokio::sync::RwLock,
};
type DynamicMap = HashMap<TypeId, Box<dyn Any + Send + Sync>>;
#[derive(Debug, Clone, Default)]
pub struct TypeStore(Arc<RwLock<DynamicMap>>);
impl TypeStore {
pub async fn fetch<T>(&self) -> Option<T>
where
T: Clone + 'static,
{
self.0
.read()
.await
.get(&TypeId::of::<T>())
.and_then(|boxed| boxed.downcast_ref::<T>().cloned())
}
pub async fn insert<T>(&self, value: T) -> Option<T>
where
T: Send + Sync + 'static,
{
self.0
.write()
.await
.insert(TypeId::of::<T>(), Box::new(value))
.and_then(|old| old.downcast::<T>().ok().map(|boxed| *boxed))
}
pub async fn update<T>(&self, updater: impl FnOnce(&mut T))
where
T: 'static,
{
if let Some(item) = self
.0
.write()
.await
.get_mut(&TypeId::of::<T>())
.and_then(|boxed| boxed.downcast_mut::<T>())
{
updater(item);
}
}
pub async fn contains<T>(&self) -> bool
where
T: 'static,
{
self.0.read().await.contains_key(&TypeId::of::<T>())
}
pub async fn remove<T>(&self) -> Option<T>
where
T: 'static,
{
self.0
.write()
.await
.remove(&TypeId::of::<T>())
.and_then(|boxed| boxed.downcast::<T>().ok().map(|b| *b))
}
}