goggles/
local_resource_set.rs

1use std::{
2    any::{type_name, TypeId},
3    cell::{Ref, RefCell, RefMut},
4    iter,
5    ops::{Deref, DerefMut},
6};
7
8use anymap::{any::Any, Map};
9
10use crate::{
11    fetch_resources::FetchResources,
12    resources::{ResourceConflict, RwResources},
13};
14
15/// Store a set of arbitrary types inside `AtomicRefCell`s, and then access them for either reading
16/// or writing.
17pub struct ResourceSet {
18    resources: Map<dyn Any>,
19}
20
21impl Default for ResourceSet {
22    fn default() -> Self {
23        ResourceSet {
24            resources: Map::new(),
25        }
26    }
27}
28
29impl ResourceSet {
30    pub fn new() -> Self {
31        Self::default()
32    }
33
34    pub fn insert<T>(&mut self, r: T) -> Option<T>
35    where
36        T: 'static,
37    {
38        self.resources
39            .insert::<RefCell<T>>(RefCell::new(r))
40            .map(|r| r.into_inner())
41    }
42
43    pub fn remove<T>(&mut self) -> Option<T>
44    where
45        T: 'static,
46    {
47        self.resources
48            .remove::<RefCell<T>>()
49            .map(|r| r.into_inner())
50    }
51
52    pub fn contains<T>(&self) -> bool
53    where
54        T: 'static,
55    {
56        self.resources.contains::<RefCell<T>>()
57    }
58
59    /// Borrow the given resource immutably.
60    ///
61    /// # Panics
62    /// Panics if the resource has not been inserted or is already borrowed mutably.
63    pub fn borrow<T>(&self) -> Ref<T>
64    where
65        T: 'static,
66    {
67        if let Some(r) = self.resources.get::<RefCell<T>>() {
68            r.borrow()
69        } else {
70            panic!("no such resource {:?}", type_name::<T>());
71        }
72    }
73
74    /// Borrow the given resource mutably.
75    ///
76    /// # Panics
77    /// Panics if the resource has not been inserted or is already borrowed.
78    pub fn borrow_mut<T>(&self) -> RefMut<T>
79    where
80        T: 'static,
81    {
82        if let Some(r) = self.resources.get::<RefCell<T>>() {
83            r.borrow_mut()
84        } else {
85            panic!("no such resource {:?}", type_name::<T>());
86        }
87    }
88
89    /// # Panics
90    /// Panics if the resource has not been inserted.
91    pub fn get_mut<T>(&mut self) -> &mut T
92    where
93        T: 'static,
94    {
95        if let Some(r) = self.resources.get_mut::<RefCell<T>>() {
96            r.get_mut()
97        } else {
98            panic!("no such resource {:?}", type_name::<T>());
99        }
100    }
101
102    /// Fetch the given `FetchResources`.
103    pub fn fetch<'a, F>(&'a self) -> F
104    where
105        F: FetchResources<'a, Source = ResourceSet, Resources = RwResources<ResourceId>>,
106    {
107        F::fetch(self)
108    }
109}
110
111#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
112pub struct ResourceId(TypeId);
113
114impl ResourceId {
115    pub fn of<C: 'static>() -> ResourceId {
116        ResourceId(TypeId::of::<C>())
117    }
118}
119
120/// `SystemData` type that reads the given resource.
121///
122/// # Panics
123/// Panics if the resource does not exist or has already been borrowed for writing.
124pub struct Read<'a, T>(Ref<'a, T>);
125
126impl<'a, T> FetchResources<'a> for Read<'a, T>
127where
128    T: 'static,
129{
130    type Source = ResourceSet;
131    type Resources = RwResources<ResourceId>;
132
133    fn check_resources() -> Result<RwResources<ResourceId>, ResourceConflict> {
134        Ok(RwResources::from_iters(
135            iter::once(ResourceId::of::<T>()),
136            iter::empty(),
137        ))
138    }
139
140    fn fetch(set: &'a ResourceSet) -> Self {
141        Read(set.borrow())
142    }
143}
144
145impl<'a, T> Deref for Read<'a, T> {
146    type Target = T;
147
148    fn deref(&self) -> &T {
149        &*self.0
150    }
151}
152
153/// `SystemData` type that writes the given resource.
154///
155/// # Panics
156/// Panics if the resource does not exist or has already been borrowed for writing.
157pub struct Write<'a, T>(RefMut<'a, T>);
158
159impl<'a, T> FetchResources<'a> for Write<'a, T>
160where
161    T: 'static,
162{
163    type Source = ResourceSet;
164    type Resources = RwResources<ResourceId>;
165
166    fn check_resources() -> Result<RwResources<ResourceId>, ResourceConflict> {
167        Ok(RwResources::from_iters(
168            iter::empty(),
169            iter::once(ResourceId::of::<T>()),
170        ))
171    }
172
173    fn fetch(set: &'a ResourceSet) -> Self {
174        Write(set.borrow_mut())
175    }
176}
177
178impl<'a, T> Deref for Write<'a, T> {
179    type Target = T;
180
181    fn deref(&self) -> &T {
182        &*self.0
183    }
184}
185
186impl<'a, T> DerefMut for Write<'a, T> {
187    fn deref_mut(&mut self) -> &mut T {
188        &mut *self.0
189    }
190}