Skip to main content

euv_engine/asset/
struct.rs

1use super::*;
2
3/// An entry in the asset cache containing the loaded data and its state.
4#[derive(Clone, Data, Debug, New, PartialEq)]
5pub struct AssetEntry {
6    /// The type of this asset.
7    #[get(type(copy))]
8    pub(crate) asset_type: AssetType,
9    /// The current loading state.
10    #[get(type(copy))]
11    pub(crate) state: AssetState,
12    /// The loaded image element, if this is an image asset.
13    #[get(type(clone))]
14    pub(crate) image: Option<HtmlImageElement>,
15    /// The URL this asset was loaded from.
16    pub(crate) url: String,
17}
18
19/// A cache for storing loaded game assets, keyed by URL.
20#[derive(Clone, Data, Debug, New, PartialEq)]
21pub struct AssetCache {
22    /// All cached assets keyed by their source URL.
23    #[get_mut(pub(crate))]
24    #[set(pub(crate))]
25    #[new(skip)]
26    pub(crate) entries: HashMap<String, AssetEntry>,
27}
28
29/// An asynchronous asset loader that fetches resources over HTTP
30/// and populates a shared `AssetCache`.
31#[derive(Clone, Data, New)]
32pub struct AssetLoader {
33    /// The shared cache that loaded assets are stored into.
34    #[new(skip)]
35    pub(crate) cache: Rc<EngineCell<AssetCache>>,
36    /// The shared counter of loads that have been requested but have not
37    /// settled yet. Read through [`AssetLoader::pending_count`].
38    #[new(skip)]
39    pub(crate) pending: AssetPending,
40    /// Stored closures keeping `onload`/`onerror` callbacks alive, preventing memory leaks.
41    #[new(skip)]
42    pub(crate) closures: AssetClosures,
43}
44
45/// The backing store behind [`AssetClosures`].
46///
47/// Slots are appended in pairs by [`AssetLoader::load_image`] — even indices
48/// hold an `onload` closure, odd indices the matching `onerror` closure — so
49/// a callback can identify its own slot with one captured index.
50///
51/// The fields are public because the type is reachable from the public
52/// [`AssetClosures`] alias: a private-field type exposed through a public
53/// alias would be unusable to callers, and the retained-slot count is
54/// genuinely useful as a leak diagnostic.
55#[derive(Debug, Default)]
56pub struct AssetClosureStore {
57    /// The load callbacks, in registration order. A `None` slot is one that
58    /// has already been released by [`AssetLoader::collect`].
59    pub slots: Vec<Option<Closure<dyn FnMut()>>>,
60    /// Whether the closure in the slot at the same index has run. A settled
61    /// closure cannot free itself (see [`AssetClosures`]) but is no longer
62    /// keeping anything alive that the cache still needs.
63    pub settled: Vec<bool>,
64}