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 removed: Vec<RawAssetHandle>,
24}
25
26impl<T: 'static + Send + Sync> Assets<T> {
27 pub fn new() -> Self {
28 Self {
29 storage: SlotMap::with_key(),
30 handles: HashMap::new(),
31 queue: Vec::new(),
32 removed: Vec::new(),
33 }
34 }
35
36 pub fn insert(&mut self, name: &str, asset: T) -> RawAssetHandle {
41 let handle = self.storage.insert(asset);
42 self.queue.push(handle);
43
44 if let Some(old) = self.handles.insert(name.to_string(), handle) {
45 self.storage.remove(old);
46 self.queue.retain(|h| *h != old);
47 }
48 handle
49 }
50
51 pub fn get(&self, handle: RawAssetHandle) -> Option<&T> {
53 self.storage.get(handle)
54 }
55
56 pub fn get_mut(&mut self, handle: RawAssetHandle) -> Option<&mut T> {
58 self.storage.get_mut(handle)
59 }
60
61 pub fn get_by_name(&self, name: &str) -> Option<&T> {
63 self.handles
64 .get(name)
65 .and_then(|&handle| self.storage.get(handle))
66 }
67
68 pub fn get_mut_by_name(&mut self, name: &str) -> Option<&mut T> {
70 let handle = self.handles.get(name).copied()?;
71 self.storage.get_mut(handle)
72 }
73
74 pub fn get_handle_by_name(&self, name: &str) -> Option<RawAssetHandle> {
76 self.handles.get(name).copied()
77 }
78
79 pub fn take_dirty(&mut self) -> Vec<RawAssetHandle> {
83 std::mem::take(&mut self.queue)
84 }
85
86 pub fn remove(&mut self, handle: RawAssetHandle) -> Option<T> {
88 let value = self.storage.remove(handle)?;
89
90 self.handles.retain(|_, h| *h != handle);
91 self.queue.retain(|h| *h != handle);
92 self.removed.push(handle);
93
94 Some(value)
95 }
96
97 pub fn remove_by_name(&mut self, name: &str) -> Option<T> {
99 let handle = self.handles.remove(name)?;
100 self.queue.retain(|h| *h != handle);
101 self.removed.push(handle);
102 self.storage.remove(handle)
103 }
104
105 pub fn take_removed(&mut self) -> Vec<RawAssetHandle> {
109 std::mem::take(&mut self.removed)
110 }
111
112 pub fn dirty_is_empty(&self) -> bool {
114 self.queue.is_empty()
115 }
116
117 pub fn dirty_len(&self) -> usize {
119 self.queue.len()
120 }
121
122 pub fn requeue(&mut self, handles: Vec<RawAssetHandle>) {
124 self.queue.extend(handles);
125 }
126
127 pub fn iter(&self) -> impl Iterator<Item = (RawAssetHandle, &T)> {
129 self.storage.iter()
130 }
131
132 pub fn iter_mut(&mut self) -> impl Iterator<Item = (RawAssetHandle, &mut T)> {
134 self.storage.iter_mut()
135 }
136
137 pub fn names(&self) -> impl Iterator<Item = (&str, RawAssetHandle)> {
139 self.handles
140 .iter()
141 .map(|(name, &handle)| (name.as_str(), handle))
142 }
143
144 pub fn name_for_handle(&self, handle: RawAssetHandle) -> Option<&str> {
145 self.handles
146 .iter()
147 .find(|(_, h)| **h == handle)
148 .map(|(name, _)| name.as_str())
149 }
150}
151
152impl<'a, T: 'static + Send + Sync> IntoIterator for &'a Assets<T> {
153 type Item = (RawAssetHandle, &'a T);
154 type IntoIter = slotmap::basic::Iter<'a, RawAssetHandle, T>;
155
156 fn into_iter(self) -> Self::IntoIter {
157 self.storage.iter()
158 }
159}
160
161impl<'a, T: 'static + Send + Sync> IntoIterator for &'a mut Assets<T> {
162 type Item = (RawAssetHandle, &'a mut T);
163 type IntoIter = slotmap::basic::IterMut<'a, RawAssetHandle, T>;
164
165 fn into_iter(self) -> Self::IntoIter {
166 self.storage.iter_mut()
167 }
168}
169
170pub struct ProcessedAssets<T: 'static + Send + Sync> {
175 storage: SecondaryMap<RawAssetHandle, T>,
176 pub(crate) names: HashMap<String, RawAssetHandle>,
177}
178
179impl<T: 'static + Send + Sync> ProcessedAssets<T> {
180 pub fn new() -> Self {
181 Self {
182 storage: SecondaryMap::new(),
183 names: HashMap::new(),
184 }
185 }
186
187 pub fn insert(&mut self, handle: RawAssetHandle, asset: T) -> Option<T> {
189 self.storage.insert(handle, asset)
190 }
191
192 pub fn get(&self, handle: RawAssetHandle) -> Option<&T> {
194 self.storage.get(handle)
195 }
196
197 pub fn get_mut(&mut self, handle: RawAssetHandle) -> Option<&mut T> {
199 self.storage.get_mut(handle)
200 }
201
202 pub fn remove(&mut self, handle: RawAssetHandle) -> Option<T> {
204 self.names.retain(|_, h| *h != handle);
205 self.storage.remove(handle)
206 }
207
208 pub fn contains(&self, handle: RawAssetHandle) -> bool {
210 self.storage.contains_key(handle)
211 }
212
213 pub fn iter(&self) -> impl Iterator<Item = (RawAssetHandle, &T)> {
215 self.storage.iter()
216 }
217
218 pub fn iter_mut(&mut self) -> impl Iterator<Item = (RawAssetHandle, &mut T)> {
220 self.storage.iter_mut()
221 }
222
223 pub fn get_by_name(&self, name: &str) -> Option<&T> {
224 let handle = self.names.get(name)?;
225 self.storage.get(*handle)
226 }
227}
228
229impl<'a, T: 'static + Send + Sync> IntoIterator for &'a ProcessedAssets<T> {
230 type Item = (RawAssetHandle, &'a T);
231 type IntoIter = slotmap::secondary::Iter<'a, RawAssetHandle, T>;
232
233 fn into_iter(self) -> Self::IntoIter {
234 self.storage.iter()
235 }
236}
237
238impl<'a, T: 'static + Send + Sync> IntoIterator for &'a mut ProcessedAssets<T> {
239 type Item = (RawAssetHandle, &'a mut T);
240 type IntoIter = slotmap::secondary::IterMut<'a, RawAssetHandle, T>;
241
242 fn into_iter(self) -> Self::IntoIter {
243 self.storage.iter_mut()
244 }
245}