goud_engine/assets/server/loader_registry.rs
1//! Loader registration methods for `AssetServer`.
2
3use super::core::AssetServer;
4use crate::assets::{Asset, AssetId, AssetLoader, ErasedAssetLoader, TypedAssetLoader};
5
6impl AssetServer {
7 /// Registers an asset loader for specific file extensions.
8 ///
9 /// Loaders are matched by file extension. If multiple loaders support
10 /// the same extension, the most recently registered one is used.
11 ///
12 /// # Arguments
13 ///
14 /// * `loader` - The asset loader to register
15 ///
16 /// # Example
17 ///
18 /// ```no_run
19 /// use goud_engine::assets::{Asset, AssetServer, AssetLoader, LoadContext, AssetLoadError};
20 ///
21 /// #[derive(Clone)]
22 /// struct TextAsset { content: String }
23 /// impl Asset for TextAsset {}
24 ///
25 /// #[derive(Clone)]
26 /// struct TextLoader;
27 /// impl AssetLoader for TextLoader {
28 /// type Asset = TextAsset;
29 /// type Settings = ();
30 ///
31 /// fn extensions(&self) -> &[&str] {
32 /// &["txt"]
33 /// }
34 ///
35 /// fn load<'a>(
36 /// &'a self,
37 /// bytes: &'a [u8],
38 /// _settings: &'a Self::Settings,
39 /// _context: &'a mut LoadContext,
40 /// ) -> Result<Self::Asset, AssetLoadError> {
41 /// let content = String::from_utf8(bytes.to_vec())
42 /// .map_err(|e| AssetLoadError::decode_failed(e.to_string()))?;
43 /// Ok(TextAsset { content })
44 /// }
45 /// }
46 ///
47 /// let mut server = AssetServer::new();
48 /// server.register_loader(TextLoader);
49 /// ```
50 pub fn register_loader<L: AssetLoader>(&mut self, loader: L) {
51 let typed = TypedAssetLoader::new(loader);
52 let asset_id = AssetId::of::<L::Asset>();
53
54 // Register by extensions
55 for extension in typed.extensions() {
56 let ext = extension.to_lowercase();
57 self.loaders.insert(ext, Box::new(typed.clone()));
58 }
59
60 // Register by asset type
61 self.loader_by_type.insert(asset_id, Box::new(typed));
62 }
63
64 /// Registers an asset loader with custom settings.
65 ///
66 /// # Arguments
67 ///
68 /// * `loader` - The asset loader to register
69 /// * `settings` - Custom settings for this loader
70 pub fn register_loader_with_settings<L: AssetLoader>(
71 &mut self,
72 loader: L,
73 settings: L::Settings,
74 ) {
75 let typed = TypedAssetLoader::with_settings(loader, settings);
76 let asset_id = AssetId::of::<L::Asset>();
77
78 for extension in typed.extensions() {
79 let ext = extension.to_lowercase();
80 self.loaders.insert(ext, Box::new(typed.clone()));
81 }
82
83 self.loader_by_type.insert(asset_id, Box::new(typed));
84 }
85
86 /// Returns true if a loader is registered for the given extension.
87 ///
88 /// # Example
89 ///
90 /// ```
91 /// use goud_engine::assets::AssetServer;
92 ///
93 /// let server = AssetServer::new();
94 /// // Assuming TextLoader is registered for "txt"
95 /// // assert!(server.has_loader_for_extension("txt"));
96 /// assert!(!server.has_loader_for_extension("unknown"));
97 /// ```
98 pub fn has_loader_for_extension(&self, extension: &str) -> bool {
99 self.loaders.contains_key(&extension.to_lowercase())
100 }
101
102 /// Returns true if a loader is registered for the given asset type.
103 pub fn has_loader_for_type<A: Asset>(&self) -> bool {
104 self.loader_by_type.contains_key(&AssetId::of::<A>())
105 }
106
107 /// Returns the number of registered loaders.
108 #[inline]
109 pub fn loader_count(&self) -> usize {
110 self.loader_by_type.len()
111 }
112}