moduforge_state/
resource_table.rs1use std::sync::Arc;
2use std::fmt::{self, Debug};
3
4use dashmap::DashMap;
5
6use crate::resource::Resource;
7
8pub type ResourceId = String;
10
11#[derive(Default)]
13pub struct ResourceTable {
14 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 pub fn len(&self) -> usize {
28 self.index.len()
29 }
30
31 pub fn is_empty(&self) -> bool {
33 self.index.is_empty()
34 }
35
36 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 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 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 pub fn has(
67 &self,
68 rid: ResourceId,
69 ) -> bool {
70 self.index.contains_key(&rid)
71 }
72
73 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 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 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 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 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#[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}