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}