hydrate_loader/
storage.rs

1use std::error::Error;
2
3use crate::loader::LoaderEvent;
4use crate::ArtifactTypeId;
5use crossbeam_channel::Sender;
6use hydrate_base::handle::LoaderInfoProvider;
7use hydrate_base::{ArtifactId, LoadHandle, StringHash};
8
9#[derive(Debug)]
10pub enum HandleOp {
11    Error(LoadHandle, Box<dyn Error + Send>),
12    Complete(LoadHandle),
13    Drop(LoadHandle),
14}
15
16/// Type that allows the downstream artifact storage implementation to signal that an artifact update
17/// operation has completed. See [`ArtifactStorage::load_artifact`].
18pub struct ArtifactLoadOp {
19    sender: Option<Sender<LoaderEvent>>,
20    handle: LoadHandle,
21}
22
23impl ArtifactLoadOp {
24    pub(crate) fn new(
25        sender: Sender<LoaderEvent>,
26        handle: LoadHandle,
27    ) -> Self {
28        Self {
29            sender: Some(sender),
30            handle,
31        }
32    }
33
34    /// Returns the `LoadHandle` associated with the load operation
35    pub fn load_handle(&self) -> LoadHandle {
36        self.handle
37    }
38
39    /// Signals that this load operation has completed succesfully.
40    pub fn complete(mut self) {
41        log::debug!("LoadOp for {:?} complete", self.handle);
42        let _ = self
43            .sender
44            .as_ref()
45            .unwrap()
46            .send(LoaderEvent::LoadResult(HandleOp::Complete(self.handle)));
47        self.sender = None;
48    }
49
50    /// Signals that this load operation has completed with an error.
51    pub fn error<E: Error + 'static + Send>(
52        mut self,
53        error: E,
54    ) {
55        println!("LoadOp for {:?} error {:?}", self.handle, error);
56        let _ = self
57            .sender
58            .as_ref()
59            .unwrap()
60            .send(LoaderEvent::LoadResult(HandleOp::Error(
61                self.handle,
62                Box::new(error),
63            )));
64        self.sender = None;
65    }
66}
67
68impl Drop for ArtifactLoadOp {
69    fn drop(&mut self) {
70        if let Some(ref sender) = self.sender {
71            let _ = sender.send(LoaderEvent::LoadResult(HandleOp::Drop(self.handle)));
72        }
73    }
74}
75
76/// Storage for all artifacts of all artifact types.
77///
78/// Consumers are expected to provide the implementation for this, as this is the bridge between
79/// [`Loader`](crate::loader::Loader) and the application.
80pub trait ArtifactStorage {
81    /// Updates the backing data of an artifact.
82    ///
83    /// An example usage of this is when a texture such as "player.png" changes while the
84    /// application is running. The artifact ID is the same, but the underlying pixel data can differ.
85    ///
86    /// # Parameters
87    ///
88    /// * `loader`: Loader implementation calling this function.
89    /// * `artifact_type_id`: UUID of the artifact type.
90    /// * `data`: The updated artifact byte data.
91    /// * `load_handle`: ID allocated by [`Loader`](crate::loader::Loader) to track loading of a particular artifact.
92    /// * `load_op`: Allows the loading implementation to signal when loading is done / errors.
93    fn load_artifact(
94        &mut self,
95        loader_info: &dyn LoaderInfoProvider,
96        artifact_type_id: &ArtifactTypeId,
97        artifact_id: ArtifactId,
98        data: Vec<u8>,
99        load_handle: LoadHandle,
100        load_op: ArtifactLoadOp,
101    ) -> Result<(), Box<dyn Error + Send + 'static>>;
102
103    /// Commits the specified artifact as loaded and ready to use.
104    ///
105    /// # Parameters
106    ///
107    /// * `artifact_type`: UUID of the artifact type.
108    /// * `load_handle`: ID allocated by [`Loader`](crate::loader::Loader) to track loading of a particular artifact.
109    fn commit_artifact(
110        &mut self,
111        artifact_type: ArtifactTypeId,
112        load_handle: LoadHandle,
113    );
114
115    /// Frees the artifact identified by the load handle.
116    ///
117    /// # Parameters
118    ///
119    /// * `artifact_type_id`: UUID of the artifact type.
120    /// * `load_handle`: ID allocated by [`Loader`](crate::loader::Loader) to track loading of a particular artifact.
121    fn free_artifact(
122        &mut self,
123        artifact_type_id: ArtifactTypeId,
124        load_handle: LoadHandle,
125    );
126}
127
128/// An indirect identifier that can be resolved to a specific [`ArtifactID`] by an [`IndirectionResolver`] impl.
129#[derive(Clone, PartialEq, Eq, Debug, Hash)]
130pub enum IndirectIdentifier {
131    ArtifactId(ArtifactId, ArtifactTypeId),
132    SymbolWithType(StringHash, ArtifactTypeId),
133}