use std::any::Any;
use std::any::TypeId;
use std::any::type_name;
use std::sync::Arc;
use dashmap::DashMap;
#[derive(Default, Debug)]
pub struct GothamState {
data: DashMap<TypeId, Arc<dyn Any + Send + Sync>>,
}
impl GothamState {
pub fn put<T: Clone + Send + Sync + 'static>(
&self,
t: T,
) {
let type_id = TypeId::of::<T>();
self.data.insert(type_id, Arc::new(t));
}
pub fn has<T: Send + Sync + 'static>(&self) -> bool {
let type_id = TypeId::of::<T>();
self.data.contains_key(&type_id)
}
pub fn get<T: Clone + Send + Sync + 'static>(&self) -> Arc<T> {
self.try_get::<T>().unwrap_or_else(|| missing::<T>())
}
pub fn try_get<T: Clone + Send + Sync + 'static>(&self) -> Option<Arc<T>> {
let type_id = TypeId::of::<T>();
if let Some(v) = self.data.get(&type_id) {
let value = v.value().clone();
Arc::downcast(value).ok()
} else {
None
}
}
pub fn try_take<T: Send + Sync + 'static>(&self) -> Option<Arc<T>> {
let type_id = TypeId::of::<T>();
match self.data.remove(&type_id) {
Some((_, v)) => Arc::downcast(v).ok(),
None => None,
}
}
pub fn take<T: Send + Sync + 'static>(&mut self) -> Arc<T> {
self.try_take::<T>().unwrap_or_else(|| missing::<T>())
}
}
fn missing<T: 'static>() -> ! {
panic!(" 请求的类型 {} 不存在于 GothamState 容器中", type_name::<T>());
}