1use slotmap::{SecondaryMap, SlotMap, new_key_type};
2use std::collections::HashMap;
3
4new_key_type! {
5 pub struct RawAssetHandle;
11}
12
13pub struct Assets<T: 'static + Send + Sync> {
20 storage: SlotMap<RawAssetHandle, T>,
21 handles: HashMap<String, RawAssetHandle>,
22 queue: Vec<RawAssetHandle>,
23}
24
25impl<T: 'static + Send + Sync> Assets<T> {
26 pub fn new() -> Self {
27 Self {
28 storage: SlotMap::with_key(),
29 handles: HashMap::new(),
30 queue: Vec::new(),
31 }
32 }
33
34 pub fn insert(&mut self, name: &str, asset: T) -> RawAssetHandle {
39 let handle = self.storage.insert(asset);
40 self.queue.push(handle);
41
42 if let Some(old) = self.handles.insert(name.to_string(), handle) {
43 self.storage.remove(old);
44 self.queue.retain(|h| *h != old);
45 }
46 handle
47 }
48
49 pub fn get(&self, handle: RawAssetHandle) -> Option<&T> {
51 self.storage.get(handle)
52 }
53
54 pub fn get_mut(&mut self, handle: RawAssetHandle) -> Option<&mut T> {
56 self.storage.get_mut(handle)
57 }
58
59 pub fn get_by_name(&self, name: &str) -> Option<&T> {
61 self.handles
62 .get(name)
63 .and_then(|&handle| self.storage.get(handle))
64 }
65
66 pub fn get_mut_by_name(&mut self, name: &str) -> Option<&mut T> {
68 let handle = self.handles.get(name).copied()?;
69 self.storage.get_mut(handle)
70 }
71
72 pub fn get_handle_by_name(&self, name: &str) -> Option<RawAssetHandle> {
74 self.handles.get(name).copied()
75 }
76
77 pub fn take_dirty(&mut self) -> Vec<RawAssetHandle> {
81 std::mem::take(&mut self.queue)
82 }
83
84 pub fn remove(&mut self, handle: RawAssetHandle) -> Option<T> {
86 let value = self.storage.remove(handle)?;
87
88 self.handles.retain(|_, h| *h != handle);
89 self.queue.retain(|h| *h != handle);
90
91 Some(value)
92 }
93
94 pub fn remove_by_name(&mut self, name: &str) -> Option<T> {
96 let handle = self.handles.remove(name)?;
97 self.handles.retain(|_, h| *h != handle);
98 self.queue.retain(|h| *h != handle);
99 self.storage.remove(handle)
100 }
101
102 pub fn dirty_is_empty(&self) -> bool {
104 self.queue.is_empty()
105 }
106
107 pub fn dirty_len(&self) -> usize {
109 self.queue.len()
110 }
111
112 pub fn requeue(&mut self, handles: Vec<RawAssetHandle>) {
114 self.queue.extend(handles);
115 }
116
117 pub fn iter(&self) -> impl Iterator<Item = (RawAssetHandle, &T)> {
119 self.storage.iter()
120 }
121
122 pub fn iter_mut(&mut self) -> impl Iterator<Item = (RawAssetHandle, &mut T)> {
124 self.storage.iter_mut()
125 }
126
127 pub fn names(&self) -> impl Iterator<Item = (&str, RawAssetHandle)> {
129 self.handles
130 .iter()
131 .map(|(name, &handle)| (name.as_str(), handle))
132 }
133
134 pub fn name_for_handle(&self, handle: RawAssetHandle) -> Option<&str> {
135 self.handles
136 .iter()
137 .find(|(_, h)| **h == handle)
138 .map(|(name, _)| name.as_str())
139 }
140}
141
142impl<'a, T: 'static + Send + Sync> IntoIterator for &'a Assets<T> {
143 type Item = (RawAssetHandle, &'a T);
144 type IntoIter = slotmap::basic::Iter<'a, RawAssetHandle, T>;
145
146 fn into_iter(self) -> Self::IntoIter {
147 self.storage.iter()
148 }
149}
150
151impl<'a, T: 'static + Send + Sync> IntoIterator for &'a mut Assets<T> {
152 type Item = (RawAssetHandle, &'a mut T);
153 type IntoIter = slotmap::basic::IterMut<'a, RawAssetHandle, T>;
154
155 fn into_iter(self) -> Self::IntoIter {
156 self.storage.iter_mut()
157 }
158}
159
160pub struct ProcessedAssets<T: 'static + Send + Sync> {
165 storage: SecondaryMap<RawAssetHandle, T>,
166 pub(crate) names: HashMap<String, RawAssetHandle>,
167}
168
169impl<T: 'static + Send + Sync> ProcessedAssets<T> {
170 pub fn new() -> Self {
171 Self {
172 storage: SecondaryMap::new(),
173 names: HashMap::new(),
174 }
175 }
176
177 pub fn insert(&mut self, handle: RawAssetHandle, asset: T) -> Option<T> {
179 self.storage.insert(handle, asset)
180 }
181
182 pub fn get(&self, handle: RawAssetHandle) -> Option<&T> {
184 self.storage.get(handle)
185 }
186
187 pub fn get_mut(&mut self, handle: RawAssetHandle) -> Option<&mut T> {
189 self.storage.get_mut(handle)
190 }
191
192 pub fn remove(&mut self, handle: RawAssetHandle) -> Option<T> {
194 self.names.retain(|_, h| *h != handle);
195 self.storage.remove(handle)
196 }
197
198 pub fn contains(&self, handle: RawAssetHandle) -> bool {
200 self.storage.contains_key(handle)
201 }
202
203 pub fn iter(&self) -> impl Iterator<Item = (RawAssetHandle, &T)> {
205 self.storage.iter()
206 }
207
208 pub fn iter_mut(&mut self) -> impl Iterator<Item = (RawAssetHandle, &mut T)> {
210 self.storage.iter_mut()
211 }
212
213 pub fn get_by_name(&self, name: &str) -> Option<&T> {
214 let handle = self.names.get(name)?;
215 self.storage.get(*handle)
216 }
217}
218
219impl<'a, T: 'static + Send + Sync> IntoIterator for &'a ProcessedAssets<T> {
220 type Item = (RawAssetHandle, &'a T);
221 type IntoIter = slotmap::secondary::Iter<'a, RawAssetHandle, T>;
222
223 fn into_iter(self) -> Self::IntoIter {
224 self.storage.iter()
225 }
226}
227
228impl<'a, T: 'static + Send + Sync> IntoIterator for &'a mut ProcessedAssets<T> {
229 type Item = (RawAssetHandle, &'a mut T);
230 type IntoIter = slotmap::secondary::IterMut<'a, RawAssetHandle, T>;
231
232 fn into_iter(self) -> Self::IntoIter {
233 self.storage.iter_mut()
234 }
235}