moduforge_state/
resource_table.rs

1use std::sync::Arc;
2use std::fmt::{self, Debug};
3
4use dashmap::DashMap;
5
6use crate::resource::Resource;
7
8// 资源ID类型定义
9pub type ResourceId = String;
10
11// 资源表结构体,用于管理所有资源
12#[derive(Default)]
13pub struct ResourceTable {
14    // 使用BTreeMap存储资源ID到资源的映射
15    index: DashMap<ResourceId, Arc<dyn Resource>>,
16}
17impl Debug for ResourceTable {
18    fn fmt(
19        &self,
20        f: &mut fmt::Formatter<'_>,
21    ) -> fmt::Result {
22        write!(f, "ResourceTable {{ len: {} }}", self.index.len())
23    }
24}
25impl ResourceTable {
26    // 获取资源表中资源的数量
27    pub fn len(&self) -> usize {
28        self.index.len()
29    }
30
31    // 检查资源表是否为空
32    pub fn is_empty(&self) -> bool {
33        self.index.is_empty()
34    }
35
36    // 添加一个新资源到资源表,返回分配的资源ID
37    pub fn add<T: Resource>(
38        &self,
39        rid: ResourceId,
40        resource: T,
41    ) {
42        self.add_arc(rid, Arc::new(resource));
43    }
44
45    // 添加一个Arc包装的资源到资源表
46    pub fn add_arc<T: Resource>(
47        &self,
48        rid: ResourceId,
49        resource: Arc<T>,
50    ) {
51        let resource = resource as Arc<dyn Resource>;
52        self.add_arc_dyn(rid, resource);
53    }
54
55    // 添加一个动态类型的Arc资源到资源表
56    pub fn add_arc_dyn(
57        &self,
58        rid: ResourceId,
59        resource: Arc<dyn Resource>,
60    ) {
61        let removed_resource = self.index.insert(rid, resource);
62        assert!(removed_resource.is_none());
63    }
64
65    // 检查指定ID的资源是否存在
66    pub fn has(
67        &self,
68        rid: ResourceId,
69    ) -> bool {
70        self.index.contains_key(&rid)
71    }
72
73    // 获取指定ID的特定类型资源
74    pub fn get<T: Resource>(
75        &self,
76        rid: ResourceId,
77    ) -> Option<Arc<T>> {
78        let data = self
79            .index
80            .get(&rid)
81            .map(|rc| rc.value().clone())
82            .and_then(|rc| rc.downcast_arc::<T>().cloned());
83        data
84    }
85
86    // 获取指定ID的任意类型资源
87    pub fn get_any(
88        &self,
89        rid: ResourceId,
90    ) -> Option<Arc<dyn Resource>> {
91        self.index.get(&rid).map(|rc| rc.value().clone())
92    }
93
94    // 替换指定ID的资源
95    pub fn replace<T: Resource>(
96        &self,
97        rid: ResourceId,
98        resource: T,
99    ) {
100        let result =
101            self.index.insert(rid, Arc::new(resource) as Arc<dyn Resource>);
102        assert!(result.is_some());
103    }
104
105    // 从资源表中移除并返回指定ID的特定类型资源
106    pub fn take<T: Resource>(
107        &self,
108        rid: ResourceId,
109    ) -> Option<Arc<T>> {
110        let resource = self.get::<T>(rid.clone())?;
111        self.index.remove(&rid);
112        Some(resource)
113    }
114
115    // 从资源表中移除并返回指定ID的任意类型资源
116    pub fn take_any(
117        &self,
118        rid: ResourceId,
119    ) -> Option<Arc<dyn Resource>> {
120        self.index.remove(&rid).map(|rc| rc.1)
121    }
122}
123
124// 资源错误类型定义
125#[derive(Debug, thiserror::Error)]
126pub enum ResourceError {
127    #[error("null or invalid handle")]
128    Reference,
129    #[error("Bad resource ID")]
130    BadResourceId,
131    #[error("Resource is unavailable because it is in use by a promise")]
132    Unavailable,
133    #[error("{0}")]
134    Other(String),
135}