1use hydrate_base::{
2 handle::{ArtifactHandle, RefOp, TypedArtifactStorage},
3 ArtifactId, LoadHandle,
4};
5use std::{collections::HashMap, error::Error, sync::Mutex};
6
7use crate::storage::{ArtifactLoadOp, ArtifactStorage};
8use crate::ArtifactTypeId;
9use crossbeam_channel::{Receiver, Sender};
10use downcast_rs::Downcast;
11use hydrate_base::handle::LoaderInfoProvider;
12use hydrate_base::handle::SerdeContext;
13use std::marker::PhantomData;
14use type_uuid::TypeUuid;
15
16pub trait DynArtifactStorage: Downcast + Send {
18 fn load_artifact(
19 &mut self,
20 loader_info: &dyn LoaderInfoProvider,
21 artifact_id: ArtifactId,
22 data: &[u8],
23 load_handle: LoadHandle,
24 load_op: ArtifactLoadOp,
25 ) -> Result<(), Box<dyn Error + Send + 'static>>;
26 fn commit_artifact(
27 &mut self,
28 handle: LoadHandle,
29 );
30 fn free_artifact(
31 &mut self,
32 handle: LoadHandle,
33 );
34
35 fn type_name(&self) -> &'static str;
36}
37
38downcast_rs::impl_downcast!(DynArtifactStorage);
39
40pub struct ArtifactStorageSetInner {
41 storage: HashMap<ArtifactTypeId, Box<dyn DynArtifactStorage>>,
42 data_to_artifact_type_uuid: HashMap<ArtifactTypeId, ArtifactTypeId>,
43 artifact_to_data_type_uuid: HashMap<ArtifactTypeId, ArtifactTypeId>,
44 refop_sender: Sender<RefOp>,
45}
46
47pub struct ArtifactStorageSet {
49 inner: Mutex<ArtifactStorageSetInner>,
50}
51
52impl ArtifactStorageSet {
53 pub fn new(refop_sender: Sender<RefOp>) -> Self {
54 let inner = ArtifactStorageSetInner {
55 storage: Default::default(),
56 data_to_artifact_type_uuid: Default::default(),
57 artifact_to_data_type_uuid: Default::default(),
58 refop_sender,
59 };
60
61 Self {
62 inner: Mutex::new(inner),
63 }
64 }
65
66 pub fn add_storage<T>(&self)
67 where
68 T: TypeUuid + for<'a> serde::Deserialize<'a> + 'static + Send,
69 {
70 let mut inner = self.inner.lock().unwrap();
71 let refop_sender = inner.refop_sender.clone();
72 let old = inner.data_to_artifact_type_uuid.insert(
73 ArtifactTypeId::from_bytes(T::UUID),
74 ArtifactTypeId::from_bytes(T::UUID),
75 );
76 assert!(old.is_none());
77 let old = inner.artifact_to_data_type_uuid.insert(
78 ArtifactTypeId::from_bytes(T::UUID),
79 ArtifactTypeId::from_bytes(T::UUID),
80 );
81 assert!(old.is_none());
82 inner.storage.insert(
83 ArtifactTypeId::from_bytes(T::UUID),
84 Box::new(Storage::<T>::new(
85 refop_sender,
86 Box::new(DefaultArtifactLoader::default()),
87 )),
88 );
89 }
90
91 pub fn add_storage_with_loader<ArtifactDataT, ArtifactT, LoaderT>(
92 &self,
93 loader: Box<LoaderT>,
94 ) where
95 ArtifactDataT: TypeUuid + for<'a> serde::Deserialize<'a> + 'static,
96 ArtifactT: TypeUuid + 'static + Send,
97 LoaderT: DynArtifactLoader<ArtifactT> + 'static,
98 {
99 let mut inner = self.inner.lock().unwrap();
100 let refop_sender = inner.refop_sender.clone();
101 let old = inner.data_to_artifact_type_uuid.insert(
102 ArtifactTypeId::from_bytes(ArtifactDataT::UUID),
103 ArtifactTypeId::from_bytes(ArtifactT::UUID),
104 );
105 assert!(old.is_none());
106 let old = inner.artifact_to_data_type_uuid.insert(
107 ArtifactTypeId::from_bytes(ArtifactT::UUID),
108 ArtifactTypeId::from_bytes(ArtifactDataT::UUID),
109 );
110 assert!(old.is_none());
111 inner.storage.insert(
112 ArtifactTypeId::from_bytes(ArtifactT::UUID),
113 Box::new(Storage::<ArtifactT>::new(refop_sender, loader)),
114 );
115 }
116
117 pub fn artifact_to_data_type_uuid<ArtifactT>(&self) -> Option<ArtifactTypeId>
118 where
119 ArtifactT: TypeUuid + 'static + Send,
120 {
121 let inner = self.inner.lock().unwrap();
122 inner
123 .artifact_to_data_type_uuid
124 .get(&ArtifactTypeId::from_bytes(ArtifactT::UUID))
125 .cloned()
126 }
127}
128
129impl ArtifactStorage for ArtifactStorageSet {
132 fn load_artifact(
133 &mut self,
134 loader_info: &dyn LoaderInfoProvider,
135 artifact_type_id: &ArtifactTypeId,
136 artifact_id: ArtifactId,
137 data: Vec<u8>,
138 load_handle: LoadHandle,
139 load_op: ArtifactLoadOp,
140 ) -> Result<(), Box<dyn Error + Send + 'static>> {
141 let mut inner = self.inner.lock().unwrap();
142
143 let artifact_type_id = *inner
144 .data_to_artifact_type_uuid
145 .get(artifact_type_id)
146 .expect("unknown artifact data type");
147
148 let x = inner
149 .storage
150 .get_mut(&artifact_type_id)
151 .expect("unknown artifact type")
152 .load_artifact(loader_info, artifact_id, &data, load_handle, load_op);
153 x
154 }
155
156 fn commit_artifact(
157 &mut self,
158 artifact_data_type_id: ArtifactTypeId,
159 load_handle: LoadHandle,
160 ) {
161 let mut inner = self.inner.lock().unwrap();
162
163 let artifact_type_id = *inner
164 .data_to_artifact_type_uuid
165 .get(&artifact_data_type_id)
166 .expect("unknown artifact data type");
167
168 inner
169 .storage
170 .get_mut(&artifact_type_id)
171 .expect("unknown artifact type")
172 .commit_artifact(load_handle)
173 }
174
175 fn free_artifact(
176 &mut self,
177 artifact_data_type_id: ArtifactTypeId,
178 load_handle: LoadHandle,
179 ) {
180 let mut inner = self.inner.lock().unwrap();
181
182 let artifact_type_id = *inner
183 .data_to_artifact_type_uuid
184 .get(&artifact_data_type_id)
185 .expect("unknown artifact data type");
186
187 inner
188 .storage
189 .get_mut(&artifact_type_id)
190 .expect("unknown artifact type")
191 .free_artifact(load_handle)
192 }
193}
194
195impl<A: TypeUuid + 'static + Send> TypedArtifactStorage<A> for ArtifactStorageSet {
198 fn get<T: ArtifactHandle>(
199 &self,
200 handle: &T,
201 ) -> Option<&A> {
202 unsafe {
204 std::mem::transmute(
205 self.inner
206 .lock()
207 .unwrap()
208 .storage
209 .get(&ArtifactTypeId::from_bytes(A::UUID))
210 .expect("unknown artifact type")
211 .as_ref()
212 .downcast_ref::<Storage<A>>()
213 .expect("failed to downcast")
214 .get(handle),
215 )
216 }
217 }
218}
219
220pub enum UpdateArtifactResult<ArtifactT>
222where
223 ArtifactT: Send,
224{
225 Result(ArtifactT),
226 AsyncResult(Receiver<ArtifactT>),
227}
228
229pub trait DynArtifactLoader<ArtifactT>: Send
232where
233 ArtifactT: TypeUuid + 'static + Send,
234{
235 fn load_artifact(
236 &mut self,
237 refop_sender: &Sender<RefOp>,
238 loader_info: &dyn LoaderInfoProvider,
239 data: &[u8],
240 load_handle: LoadHandle,
241 load_op: ArtifactLoadOp,
242 ) -> Result<UpdateArtifactResult<ArtifactT>, Box<dyn Error + Send + 'static>>;
243
244 fn commit_artifact(
245 &mut self,
246 handle: LoadHandle,
247 );
248
249 fn free_artifact(
250 &mut self,
251 handle: LoadHandle,
252 );
253}
254
255struct DefaultArtifactLoader<ArtifactDataT>
257where
258 ArtifactDataT: TypeUuid + Send + for<'a> serde::Deserialize<'a> + 'static,
259{
260 phantom_data: PhantomData<ArtifactDataT>,
261}
262
263impl<ArtifactDataT> Default for DefaultArtifactLoader<ArtifactDataT>
264where
265 ArtifactDataT: TypeUuid + Send + for<'a> serde::Deserialize<'a> + 'static,
266{
267 fn default() -> Self {
268 DefaultArtifactLoader {
269 phantom_data: Default::default(),
270 }
271 }
272}
273
274impl<ArtifactDataT> DynArtifactLoader<ArtifactDataT> for DefaultArtifactLoader<ArtifactDataT>
275where
276 ArtifactDataT: TypeUuid + Send + for<'a> serde::Deserialize<'a> + 'static,
277{
278 fn load_artifact(
279 &mut self,
280 refop_sender: &Sender<RefOp>,
281 loader_info: &dyn LoaderInfoProvider,
282 data: &[u8],
283 _load_handle: LoadHandle,
284 load_op: ArtifactLoadOp,
285 ) -> Result<UpdateArtifactResult<ArtifactDataT>, Box<dyn Error + Send + 'static>> {
286 log::debug!("DefaultArtifactLoader load_artifact");
287
288 let artifact_data = SerdeContext::with(loader_info, refop_sender.clone(), || {
289 log::debug!("bincode deserialize");
290 let x = bincode::deserialize::<ArtifactDataT>(data)
291 .map_err(|x| -> Box<dyn Error + Send + 'static> { Box::new(x) });
293 println!("finished deserialize");
294 x
295 })?;
296 log::debug!("call load_op.complete()");
297
298 load_op.complete();
299 log::debug!("return");
300 Ok(UpdateArtifactResult::Result(artifact_data))
301 }
302
303 fn commit_artifact(
304 &mut self,
305 _handle: LoadHandle,
306 ) {
307 }
308
309 fn free_artifact(
310 &mut self,
311 _handle: LoadHandle,
312 ) {
313 }
314}
315
316struct UncommittedArtifactState<A: Send> {
317 artifact_id: ArtifactId,
318 result: UpdateArtifactResult<A>,
319}
320
321struct ArtifactState<A> {
322 artifact_id: ArtifactId,
323 artifact: A,
324}
325
326pub struct Storage<ArtifactT: TypeUuid + Send> {
328 refop_sender: Sender<RefOp>,
329 artifacts: HashMap<LoadHandle, ArtifactState<ArtifactT>>,
330 uncommitted: HashMap<LoadHandle, UncommittedArtifactState<ArtifactT>>,
331 loader: Box<dyn DynArtifactLoader<ArtifactT>>,
332}
333
334impl<ArtifactT: TypeUuid + Send> Storage<ArtifactT> {
335 fn new(
336 sender: Sender<RefOp>,
337 loader: Box<dyn DynArtifactLoader<ArtifactT>>,
338 ) -> Self {
339 Self {
340 refop_sender: sender,
341 artifacts: HashMap::new(),
342 uncommitted: HashMap::new(),
343 loader,
344 }
345 }
346 fn get<T: ArtifactHandle>(
347 &self,
348 handle: &T,
349 ) -> Option<&ArtifactT> {
350 let handle = handle.direct_load_handle();
351 self.artifacts.get(&handle).map(|a| &a.artifact)
352 }
353}
354
355impl<ArtifactT: TypeUuid + 'static + Send> DynArtifactStorage for Storage<ArtifactT> {
356 fn load_artifact(
357 &mut self,
358 loader_info: &dyn LoaderInfoProvider,
359 artifact_id: ArtifactId,
360 data: &[u8],
361 load_handle: LoadHandle,
362 load_op: ArtifactLoadOp,
363 ) -> Result<(), Box<dyn Error + Send + 'static>> {
364 log::debug!(
365 "load_artifact {} {:?} {:?}",
366 core::any::type_name::<ArtifactT>(),
367 load_handle,
368 artifact_id,
369 );
370
371 let result = self.loader.load_artifact(
372 &self.refop_sender,
373 loader_info,
374 data,
375 load_handle,
376 load_op,
377 )?;
378
379 self.uncommitted.insert(
381 load_handle,
382 UncommittedArtifactState {
383 artifact_id,
384 result,
385 },
386 );
387
388 Ok(())
389 }
390
391 fn commit_artifact(
392 &mut self,
393 load_handle: LoadHandle,
394 ) {
395 let uncommitted_artifact_state = self
397 .uncommitted
398 .remove(&load_handle)
399 .expect("artifact not present when committing");
400
401 log::debug!(
402 "commit_artifact {} {:?} {:?}",
403 core::any::type_name::<ArtifactT>(),
404 load_handle,
405 uncommitted_artifact_state.artifact_id,
406 );
407
408 let artifact_id = uncommitted_artifact_state.artifact_id;
409 let artifact = match uncommitted_artifact_state.result {
410 UpdateArtifactResult::Result(artifact) => artifact,
411 UpdateArtifactResult::AsyncResult(rx) => rx
412 .try_recv()
413 .expect("LoadOp committed but result not sent via channel"),
414 };
415
416 self.loader.commit_artifact(load_handle);
418
419 let artifact_state = ArtifactState {
420 artifact,
421 artifact_id,
422 };
423
424 self.artifacts.insert(load_handle, artifact_state);
426 }
427
428 fn free_artifact(
429 &mut self,
430 load_handle: LoadHandle,
431 ) {
432 if let Some(artifact_state) = self.artifacts.remove(&load_handle) {
433 log::debug!(
434 "free {} {:?} {:?}",
435 core::any::type_name::<ArtifactT>(),
436 load_handle,
437 artifact_state.artifact_id
438 );
439 self.loader.free_artifact(load_handle);
441 }
442 }
443
444 fn type_name(&self) -> &'static str {
445 core::any::type_name::<Self>()
446 }
447}