1use std::any::TypeId;
14use std::marker::PhantomData;
15use std::prelude::v1::*;
16
17use downcast_rs::Downcast;
18use fnv::FnvHashMap as HashMap;
19
20use crate::trust_cell::{Ref, RefMut, TrustCell};
21
22#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
25pub struct ResourceId {
26 type_id: TypeId,
27}
28
29impl ResourceId {
30 #[inline]
32 pub fn new<T: 'static>() -> Self {
33 ResourceId {
34 type_id: std::any::TypeId::of::<T>(),
35 }
36 }
37}
38
39pub trait Resource: Downcast + Send + Sync + 'static {}
42
43impl<T> Resource for T where T: Downcast + Send + Sync {}
44
45mod __resource_mopafy_scope {
47 #![allow(clippy::all)]
48
49 use super::Resource;
50
51 downcast_rs::impl_downcast!(Resource);
52}
53
54pub struct ResourceMapBuilder {
56 resource_map: ResourceMap,
58}
59
60impl ResourceMapBuilder {
61 pub fn new() -> Self {
63 ResourceMapBuilder {
64 resource_map: ResourceMap::new(),
65 }
66 }
67
68 pub fn with_resource<R>(
70 mut self,
71 r: R,
72 ) -> Self
73 where
74 R: Resource,
75 {
76 self.resource_map.insert(r);
77 self
78 }
79
80 pub fn insert<R>(
82 &mut self,
83 r: R,
84 ) where
85 R: Resource,
86 {
87 self.resource_map.insert(r);
88 }
89
90 pub fn build(self) -> ResourceMap {
92 self.resource_map
93 }
94}
95
96#[derive(Default)]
98pub struct ResourceMap {
99 resources: HashMap<ResourceId, TrustCell<Box<dyn Resource>>>,
100}
101
102impl ResourceMap {
103 pub fn new() -> Self {
105 ResourceMap {
106 resources: HashMap::default(),
107 }
108 }
109
110 pub fn try_insert_default<R>(&mut self)
111 where
112 R: Resource + Default,
113 {
114 if !self.has_value::<R>() {
115 self.insert(R::default());
116 }
117 }
118
119 pub fn insert<R>(
121 &mut self,
122 r: R,
123 ) where
124 R: Resource,
125 {
126 self.insert_by_id(ResourceId::new::<R>(), r);
127 }
128
129 pub fn remove<R>(&mut self) -> Option<R>
131 where
132 R: Resource,
133 {
134 self.remove_by_id(ResourceId::new::<R>())
135 }
136
137 fn insert_by_id<R>(
138 &mut self,
139 id: ResourceId,
140 r: R,
141 ) where
142 R: Resource,
143 {
144 let _old = self.resources.insert(id, TrustCell::new(Box::new(r)));
146 }
148
149 fn remove_by_id<R>(
150 &mut self,
151 id: ResourceId,
152 ) -> Option<R>
153 where
154 R: Resource,
155 {
156 self.resources
157 .remove(&id)
158 .map(TrustCell::into_inner)
159 .map(|x: Box<dyn Resource>| x.downcast())
160 .map(|x: Result<Box<R>, _>| x.ok().unwrap())
161 .map(|x| *x)
162 }
163
164 fn unwrap_resource<R>(resource: Option<R>) -> R {
165 if resource.is_none() {
166 let name = core::any::type_name::<R>();
167 panic!("Resource not found: {}", name);
169 }
170
171 resource.unwrap()
172 }
173
174 pub fn fetch<R: Resource>(&self) -> ReadBorrow<R> {
178 let result = self.try_fetch();
179 Self::unwrap_resource(result)
180 }
181
182 pub fn try_fetch<R: Resource>(&self) -> Option<ReadBorrow<R>> {
185 let res_id = ResourceId::new::<R>();
186
187 self.resources.get(&res_id).map(|r| ReadBorrow {
188 inner: Ref::map(r.borrow(), Box::as_ref),
189 phantom: PhantomData,
190 })
191 }
192
193 pub fn fetch_mut<R: Resource>(&self) -> WriteBorrow<R> {
197 let result = self.try_fetch_mut();
198 Self::unwrap_resource(result)
199 }
200
201 pub fn try_fetch_mut<R: Resource>(&self) -> Option<WriteBorrow<R>> {
204 let res_id = ResourceId::new::<R>();
205
206 self.resources.get(&res_id).map(|r| WriteBorrow::<R> {
207 inner: RefMut::map(r.borrow_mut(), Box::as_mut),
208 phantom: PhantomData,
209 })
210 }
211
212 pub fn has_value<R>(&self) -> bool
214 where
215 R: Resource,
216 {
217 self.has_value_raw(ResourceId::new::<R>())
218 }
219
220 fn has_value_raw(
221 &self,
222 id: ResourceId,
223 ) -> bool {
224 self.resources.contains_key(&id)
225 }
226
227 pub fn keys(&self) -> impl Iterator<Item = &ResourceId> {
229 self.resources.iter().map(|x| x.0)
230 }
231}
232
233pub trait DataRequirement<'a> {
235 type Borrow: DataBorrow;
236
237 fn fetch(resource_map: &'a ResourceMap) -> Self::Borrow;
238}
239
240impl<'a> DataRequirement<'a> for () {
242 type Borrow = ();
243
244 fn fetch(_: &'a ResourceMap) -> Self::Borrow {}
245}
246
247pub struct Read<T: Resource> {
250 phantom_data: PhantomData<T>,
251}
252
253pub type ReadOption<T> = Option<Read<T>>;
255
256impl<'a, T: Resource> DataRequirement<'a> for Read<T> {
257 type Borrow = ReadBorrow<'a, T>;
258
259 fn fetch(resource_map: &'a ResourceMap) -> Self::Borrow {
260 resource_map.fetch::<T>()
261 }
262}
263
264impl<'a, T: Resource> DataRequirement<'a> for Option<Read<T>> {
265 type Borrow = Option<ReadBorrow<'a, T>>;
266
267 fn fetch(resource_map: &'a ResourceMap) -> Self::Borrow {
268 resource_map.try_fetch::<T>()
269 }
270}
271
272pub struct Write<T: Resource> {
275 phantom_data: PhantomData<T>,
276}
277
278pub type WriteOption<T> = Option<Write<T>>;
280
281impl<'a, T: Resource> DataRequirement<'a> for Write<T> {
282 type Borrow = WriteBorrow<'a, T>;
283
284 fn fetch(resource_map: &'a ResourceMap) -> Self::Borrow {
285 resource_map.fetch_mut::<T>()
286 }
287}
288
289impl<'a, T: Resource> DataRequirement<'a> for Option<Write<T>> {
290 type Borrow = Option<WriteBorrow<'a, T>>;
291
292 fn fetch(resource_map: &'a ResourceMap) -> Self::Borrow {
293 resource_map.try_fetch_mut::<T>()
294 }
295}
296
297pub trait DataBorrow {}
300
301impl DataBorrow for () {}
303
304pub struct ReadBorrow<'a, T> {
306 inner: Ref<'a, dyn Resource>,
307 phantom: PhantomData<&'a T>,
308}
309
310impl<'a, T> DataBorrow for ReadBorrow<'a, T> {}
311impl<'a, T> DataBorrow for Option<ReadBorrow<'a, T>> {}
312
313impl<'a, T> std::ops::Deref for ReadBorrow<'a, T>
314where
315 T: Resource,
316{
317 type Target = T;
318
319 fn deref(&self) -> &T {
320 self.inner.downcast_ref().unwrap()
321 }
322}
323
324impl<'a, T> Clone for ReadBorrow<'a, T> {
325 fn clone(&self) -> Self {
326 ReadBorrow {
327 inner: self.inner.clone(),
328 phantom: PhantomData,
329 }
330 }
331}
332
333pub struct WriteBorrow<'a, T> {
335 inner: RefMut<'a, dyn Resource>,
336 phantom: PhantomData<&'a mut T>,
337}
338
339impl<'a, T> DataBorrow for WriteBorrow<'a, T> {}
340impl<'a, T> DataBorrow for Option<WriteBorrow<'a, T>> {}
341
342impl<'a, T> std::ops::Deref for WriteBorrow<'a, T>
343where
344 T: Resource,
345{
346 type Target = T;
347
348 fn deref(&self) -> &T {
349 self.inner.downcast_ref().unwrap()
350 }
351}
352
353impl<'a, T> std::ops::DerefMut for WriteBorrow<'a, T>
354where
355 T: Resource,
356{
357 fn deref_mut(&mut self) -> &mut T {
358 self.inner.downcast_mut().unwrap()
359 }
360}
361
362macro_rules! impl_data {
364 ( $($ty:ident),* ) => {
365
366 impl<$($ty),*> DataBorrow for ( $( $ty , )* )
370 where $( $ty : DataBorrow ),*
371 {
372
373 }
374
375 impl<'a, $($ty),*> DataRequirement<'a> for ( $( $ty , )* )
380 where $( $ty : DataRequirement<'a> ),*
381 {
382 type Borrow = ( $( <$ty as DataRequirement<'a>>::Borrow, )* );
383
384 fn fetch(resource_map: &'a ResourceMap) -> Self::Borrow {
385 #![allow(unused_variables)]
386 ( $( <$ty as DataRequirement<'a>>::fetch(resource_map), )* )
387 }
388 }
389 };
390}
391
392mod impl_data {
393 #![cfg_attr(rustfmt, rustfmt_skip)]
394
395 use super::*;
396
397 impl_data!(A);
399 impl_data!(A, B);
400 impl_data!(A, B, C);
401 impl_data!(A, B, C, D);
402 impl_data!(A, B, C, D, E);
403 impl_data!(A, B, C, D, E, F);
404 impl_data!(A, B, C, D, E, F, G);
405 impl_data!(A, B, C, D, E, F, G, H);
406 impl_data!(A, B, C, D, E, F, G, H, I);
407 impl_data!(A, B, C, D, E, F, G, H, I, J);
408 }