1pub mod artifact_storage;
2mod disk_io;
3pub mod loader;
4pub mod storage;
5
6pub use crate::artifact_storage::{ArtifactStorageSet, DynArtifactLoader};
7use crate::disk_io::DiskArtifactIO;
8use crate::loader::Loader;
9use crossbeam_channel::{Receiver, Sender};
10use hydrate_base::handle::RefOp;
11use hydrate_base::{ArtifactId, StringHash};
12use std::path::PathBuf;
13use type_uuid::TypeUuid;
14
15mod artifact_type_id;
16pub use artifact_type_id::ArtifactTypeId;
17
18use crate::storage::IndirectIdentifier;
19pub use hydrate_base::handle::Handle;
20
21pub fn process_ref_ops(
22 loader: &Loader,
23 rx: &Receiver<RefOp>,
24) {
25 while let Ok(ref_op) = rx.try_recv() {
26 match ref_op {
27 RefOp::Decrease(handle) => loader.remove_engine_ref(handle),
28 RefOp::Increase(handle) => {
29 loader.add_engine_ref_by_handle(handle);
30 }
31 }
32 }
33}
34
35pub struct ArtifactManager {
36 artifact_storage: ArtifactStorageSet,
37 loader: Loader,
38 ref_op_tx: Sender<RefOp>,
39 ref_op_rx: Receiver<RefOp>,
40}
41
42impl ArtifactManager {
43 pub fn new(build_data_root_path: PathBuf) -> Result<Self, String> {
44 let (ref_op_tx, ref_op_rx) = crossbeam_channel::unbounded();
45 let (loader_events_tx, loader_events_rx) = crossbeam_channel::unbounded();
46
47 let artifact_io = DiskArtifactIO::new(build_data_root_path, loader_events_tx.clone())?;
48 let loader = Loader::new(Box::new(artifact_io), loader_events_tx, loader_events_rx);
49 let artifact_storage = ArtifactStorageSet::new(ref_op_tx.clone());
50
51 let mut loader = ArtifactManager {
52 artifact_storage,
53 loader,
54 ref_op_tx,
55 ref_op_rx,
56 };
57
58 loader.update();
59
60 Ok(loader)
61 }
62
63 pub fn loader(&self) -> &Loader {
64 &self.loader
65 }
66
67 pub fn storage(&self) -> &ArtifactStorageSet {
68 &self.artifact_storage
69 }
70
71 pub fn add_storage<T>(&mut self)
72 where
73 T: TypeUuid + for<'a> serde::Deserialize<'a> + 'static + Send,
74 {
75 self.artifact_storage.add_storage::<T>();
76 }
77
78 pub fn add_storage_with_loader<ArtifactDataT, ArtifactT, LoaderT>(
79 &mut self,
80 loader: Box<LoaderT>,
81 ) where
82 ArtifactDataT: TypeUuid + for<'a> serde::Deserialize<'a> + 'static,
83 ArtifactT: TypeUuid + 'static + Send,
84 LoaderT: DynArtifactLoader<ArtifactT> + 'static,
85 {
86 self.artifact_storage
87 .add_storage_with_loader::<ArtifactDataT, ArtifactT, LoaderT>(loader);
88 }
89
90 pub fn load_artifact<T: TypeUuid + 'static + Send>(
91 &self,
92 artifact_id: ArtifactId,
93 ) -> Handle<T> {
94 let data_type_uuid = self
95 .storage()
96 .artifact_to_data_type_uuid::<T>()
97 .expect("Called load_artifact with unregistered asset type");
98 let load_handle = self
99 .loader
100 .add_engine_ref_indirect(IndirectIdentifier::ArtifactId(artifact_id, data_type_uuid));
101 Handle::<T>::new(self.ref_op_tx.clone(), load_handle)
102 }
103
104 pub fn load_artifact_symbol_name<T: TypeUuid + 'static + Send>(
105 &self,
106 symbol_name: &'static str,
107 ) -> Handle<T> {
108 self.load_artifact_symbol_string_hash(StringHash::from_static_str(symbol_name))
109 }
110
111 pub fn load_artifact_symbol_string_hash<T: TypeUuid + 'static + Send>(
112 &self,
113 symbol: StringHash,
114 ) -> Handle<T> {
115 let data_type_uuid = self
116 .storage()
117 .artifact_to_data_type_uuid::<T>()
118 .expect("Called load_artifact with unregistered asset type");
119
120 let load_handle = self
121 .loader
122 .add_engine_ref_indirect(IndirectIdentifier::SymbolWithType(symbol, data_type_uuid));
123 Handle::<T>::new(self.ref_op_tx.clone(), load_handle)
124 }
125
126 pub fn update(&mut self) {
127 process_ref_ops(&self.loader, &self.ref_op_rx);
128 self.loader.update(&mut self.artifact_storage);
129 }
130}