moduforge_state/
gotham_state.rs

1use std::any::Any;
2use std::any::TypeId;
3use std::any::type_name;
4use std::sync::Arc;
5
6use dashmap::DashMap;
7
8#[derive(Default, Debug)]
9pub struct GothamState {
10    /// 使用BTreeMap存储不同类型的数据,以TypeId为键
11    data: DashMap<TypeId, Arc<dyn Any + Send + Sync>>,
12}
13
14impl GothamState {
15    /// 将数据存入状态容器中
16    ///
17    /// # 参数
18    /// * `t` - 要存储的数据,必须是'static生命周期
19    pub fn put<T: Clone + Send + Sync + 'static>(
20        &self,
21        t: T,
22    ) {
23        let type_id = TypeId::of::<T>();
24        self.data.insert(type_id, Arc::new(t));
25    }
26
27    /// 检查状态容器中是否包含指定类型的数据
28    ///
29    /// # 参数
30    /// * 泛型参数T - 要检查的类型
31    ///
32    /// # 返回值
33    /// * 如果存在返回true,否则返回false
34    pub fn has<T: Send + Sync + 'static>(&self) -> bool {
35        let type_id = TypeId::of::<T>();
36        self.data.contains_key(&type_id)
37    }
38    pub fn get<T: Clone + Send + Sync + 'static>(&self) -> Arc<T> {
39        self.try_get::<T>().unwrap_or_else(|| missing::<T>())
40    }
41
42    pub fn try_get<T: Clone + Send + Sync + 'static>(&self) -> Option<Arc<T>> {
43        let type_id = TypeId::of::<T>();
44        if let Some(v) = self.data.get(&type_id) {
45            let value = v.value().clone();
46            Arc::downcast(value).ok()
47        } else {
48            None
49        }
50    }
51
52    pub fn try_take<T: Send + Sync + 'static>(&self) -> Option<Arc<T>> {
53        let type_id = TypeId::of::<T>();
54        match self.data.remove(&type_id) {
55            Some((_, v)) => Arc::downcast(v).ok(),
56            None => None,
57        }
58    }
59    /// 从状态容器中移除并返回指定类型的数据
60    ///
61    /// # 参数
62    /// * 泛型参数T - 要移除的类型
63    ///
64    /// # 返回值
65    /// * 返回T,如果数据不存在则panic
66    pub fn take<T: Send + Sync + 'static>(&mut self) -> Arc<T> {
67        self.try_take::<T>().unwrap_or_else(|| missing::<T>())
68    }
69}
70
71/// 当请求的类型不存在时,生成panic错误信息
72///
73/// # 参数
74/// * 泛型参数T - 缺失的类型
75///
76/// # 返回值
77/// * 永不返回,总是panic
78fn missing<T: 'static>() -> ! {
79    panic!(" 请求的类型 {} 不存在于 GothamState 容器中", type_name::<T>());
80}