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