goud_engine/assets/storage/
container.rs1use crate::assets::{
4 Asset, AssetHandle, AssetId, AssetInfo, AssetPath, AssetState, UntypedAssetHandle,
5};
6use std::collections::HashMap;
7use std::fmt;
8
9use super::any_storage::AnyAssetStorage;
10use super::entry::AssetEntry;
11use super::typed::TypedAssetStorage;
12
13pub struct AssetStorage {
49 storages: HashMap<AssetId, Box<dyn AnyAssetStorage>>,
51}
52
53impl AssetStorage {
54 #[inline]
56 pub fn new() -> Self {
57 Self {
58 storages: HashMap::new(),
59 }
60 }
61
62 #[inline]
64 pub fn with_capacity(capacity: usize) -> Self {
65 Self {
66 storages: HashMap::with_capacity(capacity),
67 }
68 }
69
70 pub fn insert<A: Asset>(&mut self, asset: A) -> AssetHandle<A> {
74 self.get_or_create_storage::<A>().insert(asset)
75 }
76
77 pub fn insert_with_path<A: Asset>(&mut self, asset: A, path: AssetPath<'_>) -> AssetHandle<A> {
81 self.get_or_create_storage::<A>()
82 .insert_with_path(asset, path)
83 }
84
85 pub fn reserve<A: Asset>(&mut self) -> AssetHandle<A> {
87 self.get_or_create_storage::<A>().reserve()
88 }
89
90 pub fn reserve_with_path<A: Asset>(&mut self, path: AssetPath<'_>) -> AssetHandle<A> {
92 self.get_or_create_storage::<A>().reserve_with_path(path)
93 }
94
95 pub fn set_loaded<A: Asset>(&mut self, handle: &AssetHandle<A>, asset: A) -> bool {
97 self.get_or_create_storage::<A>().set_loaded(handle, asset)
98 }
99
100 pub fn remove<A: Asset>(&mut self, handle: &AssetHandle<A>) -> Option<A> {
102 self.get_storage_mut::<A>().and_then(|s| s.remove(handle))
103 }
104
105 pub fn remove_untyped(&mut self, handle: &UntypedAssetHandle) -> bool {
107 self.storages
108 .get_mut(&handle.asset_id())
109 .map(|s| s.remove_untyped(handle))
110 .unwrap_or(false)
111 }
112
113 pub fn get<A: Asset>(&self, handle: &AssetHandle<A>) -> Option<&A> {
115 self.get_storage::<A>().and_then(|s| s.get(handle))
116 }
117
118 pub fn get_mut<A: Asset>(&mut self, handle: &AssetHandle<A>) -> Option<&mut A> {
120 self.get_storage_mut::<A>().and_then(|s| s.get_mut(handle))
121 }
122
123 pub fn get_entry<A: Asset>(&self, handle: &AssetHandle<A>) -> Option<&AssetEntry<A>> {
125 self.get_storage::<A>().and_then(|s| s.get_entry(handle))
126 }
127
128 pub fn get_entry_mut<A: Asset>(
130 &mut self,
131 handle: &AssetHandle<A>,
132 ) -> Option<&mut AssetEntry<A>> {
133 self.get_storage_mut::<A>()
134 .and_then(|s| s.get_entry_mut(handle))
135 }
136
137 pub fn is_alive<A: Asset>(&self, handle: &AssetHandle<A>) -> bool {
139 self.get_storage::<A>()
140 .map(|s| s.is_alive(handle))
141 .unwrap_or(false)
142 }
143
144 pub fn is_alive_untyped(&self, handle: &UntypedAssetHandle) -> bool {
146 self.storages
147 .get(&handle.asset_id())
148 .map(|s| s.is_alive_raw(handle.index(), handle.generation()))
149 .unwrap_or(false)
150 }
151
152 pub fn get_state<A: Asset>(&self, handle: &AssetHandle<A>) -> Option<AssetState> {
154 self.get_storage::<A>().and_then(|s| s.get_state(handle))
155 }
156
157 pub fn get_state_untyped(&self, handle: &UntypedAssetHandle) -> Option<AssetState> {
159 self.storages
160 .get(&handle.asset_id())
161 .and_then(|s| s.get_state_untyped(handle))
162 }
163
164 pub fn get_handle_by_path<A: Asset>(&self, path: &str) -> Option<AssetHandle<A>> {
166 self.get_storage::<A>()
167 .and_then(|s| s.get_handle_by_path(path))
168 }
169
170 pub fn get_by_path<A: Asset>(&self, path: &str) -> Option<&A> {
172 self.get_storage::<A>().and_then(|s| s.get_by_path(path))
173 }
174
175 pub fn has_path<A: Asset>(&self, path: &str) -> bool {
177 self.get_storage::<A>()
178 .map(|s| s.has_path(path))
179 .unwrap_or(false)
180 }
181
182 pub fn set_path<A: Asset>(&mut self, handle: &AssetHandle<A>, path: AssetPath<'_>) -> bool {
184 self.get_storage_mut::<A>()
185 .map(|s| s.set_path(handle, path))
186 .unwrap_or(false)
187 }
188
189 pub fn len<A: Asset>(&self) -> usize {
191 self.get_storage::<A>().map(|s| s.len()).unwrap_or(0)
192 }
193
194 pub fn is_empty_type<A: Asset>(&self) -> bool {
196 self.get_storage::<A>()
197 .map(|s| s.is_empty())
198 .unwrap_or(true)
199 }
200
201 pub fn total_len(&self) -> usize {
203 self.storages.values().map(|s| s.len()).sum()
204 }
205
206 pub fn is_empty(&self) -> bool {
208 self.storages.values().all(|s| s.is_empty())
209 }
210
211 pub fn type_count(&self) -> usize {
213 self.storages.len()
214 }
215
216 pub fn clear_type<A: Asset>(&mut self) {
218 if let Some(storage) = self.get_storage_mut::<A>() {
219 storage.clear();
220 }
221 }
222
223 pub fn clear(&mut self) {
225 for storage in self.storages.values_mut() {
226 storage.clear();
227 }
228 }
229
230 pub fn has_type<A: Asset>(&self) -> bool {
232 self.storages.contains_key(&AssetId::of::<A>())
233 }
234
235 pub fn registered_types(&self) -> Vec<AssetInfo> {
237 self.storages.values().map(|s| s.asset_info()).collect()
238 }
239
240 pub fn get_storage<A: Asset>(&self) -> Option<&TypedAssetStorage<A>> {
242 self.storages
243 .get(&AssetId::of::<A>())
244 .and_then(|s| s.as_any().downcast_ref())
245 }
246
247 pub fn get_storage_mut<A: Asset>(&mut self) -> Option<&mut TypedAssetStorage<A>> {
249 self.storages
250 .get_mut(&AssetId::of::<A>())
251 .and_then(|s| s.as_any_mut().downcast_mut())
252 }
253
254 pub fn set_loaded_raw(
258 &mut self,
259 asset_id: AssetId,
260 index: u32,
261 generation: u32,
262 boxed: Box<dyn std::any::Any + Send>,
263 ) -> bool {
264 self.storages
265 .get_mut(&asset_id)
266 .map(|s| s.set_loaded_raw(index, generation, boxed))
267 .unwrap_or(false)
268 }
269
270 pub fn replace_erased(&mut self, path: &str, boxed: Box<dyn std::any::Any + Send>) -> bool {
275 let target_id = self
277 .storages
278 .iter()
279 .find(|(_, s)| s.has_path_erased(path))
280 .map(|(id, _)| *id);
281
282 if let Some(id) = target_id {
283 if let Some(storage) = self.storages.get_mut(&id) {
284 return storage.replace_by_path(path, boxed);
285 }
286 }
287 false
288 }
289
290 pub fn set_failed_raw(
294 &mut self,
295 asset_id: AssetId,
296 index: u32,
297 generation: u32,
298 error: String,
299 ) -> bool {
300 self.storages
301 .get_mut(&asset_id)
302 .map(|s| s.set_failed_raw(index, generation, error))
303 .unwrap_or(false)
304 }
305
306 pub fn get_or_create_storage<A: Asset>(&mut self) -> &mut TypedAssetStorage<A> {
308 let id = AssetId::of::<A>();
309 self.storages
310 .entry(id)
311 .or_insert_with(|| Box::new(TypedAssetStorage::<A>::new()))
312 .as_any_mut()
313 .downcast_mut()
314 .expect("storage type mismatch")
315 }
316
317 pub fn iter<A: Asset>(&self) -> impl Iterator<Item = (AssetHandle<A>, &A)> {
319 self.get_storage::<A>().into_iter().flat_map(|s| s.iter())
320 }
321
322 pub fn handles<A: Asset>(&self) -> impl Iterator<Item = AssetHandle<A>> + '_ {
324 self.get_storage::<A>()
325 .into_iter()
326 .flat_map(|s| s.handles())
327 }
328}
329
330impl Default for AssetStorage {
331 #[inline]
332 fn default() -> Self {
333 Self::new()
334 }
335}
336
337impl fmt::Debug for AssetStorage {
338 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
339 f.debug_struct("AssetStorage")
340 .field("type_count", &self.type_count())
341 .field("total_assets", &self.total_len())
342 .finish()
343 }
344}