hydrate_base/
handle.rs

1use std::cell::RefCell;
2use std::hash::Hasher;
3use std::{
4    collections::{HashMap, HashSet},
5    fmt::Debug,
6    hash::Hash,
7    marker::PhantomData,
8    sync::{
9        atomic::{AtomicU64, Ordering},
10        Arc, Mutex, RwLock,
11    },
12};
13
14use crate::ArtifactId;
15use crossbeam_channel::Sender;
16use serde::{de, ser, Deserialize, Serialize};
17use uuid::Uuid;
18
19/// Loading ID allocated by [`Loader`](crate::loader::Loader) to track loading of a particular artifact
20/// or an indirect reference to an artifact.
21#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
22pub struct LoadHandle(pub u64);
23
24impl LoadHandle {
25    pub fn new(
26        load_handle: u64,
27        is_indirect: bool,
28    ) -> Self {
29        if is_indirect {
30            Self(load_handle | (1 << 63))
31        } else {
32            Self(load_handle)
33        }
34    }
35
36    /// Returns true if the handle needs to be resolved through the [`IndirectionTable`] before use.
37    /// An "indirect" LoadHandle represents a load operation for an identifier that is late-bound,
38    /// meaning the identifier may change which [`ArtifactId`] it resolves to.
39    /// An example of an indirect LoadHandle would be one that loads by filesystem path.
40    /// The specific artifact at a path may change as files change, move or are deleted, while a direct
41    /// LoadHandle (one that addresses by ArtifactId) is guaranteed to refer to an ArtifactId for its
42    /// whole lifetime.
43    pub fn is_indirect(&self) -> bool {
44        (self.0 & (1 << 63)) == 1 << 63
45    }
46}
47
48/// A potentially unresolved reference to an artifact
49#[derive(Debug, Hash, PartialEq, Eq, Clone, Ord, PartialOrd, Serialize, Deserialize)]
50pub struct ArtifactRef(pub ArtifactId);
51
52/// Provides information about mappings between `ArtifactId` and `LoadHandle`.
53/// Intended to be used for `Handle` serde.
54pub trait LoaderInfoProvider: Send + Sync {
55    /// Returns the load handle for the artifact with the given UUID, if present.
56    ///
57    /// This will only return `Some(..)` if there has been a previous call to [`crate::loader::Loader::add_ref`].
58    ///
59    /// # Parameters
60    ///
61    /// * `id`: UUID of the artifact.
62    fn resolved_load_handle(
63        &self,
64        artifact_ref: &ArtifactRef,
65    ) -> Option<Arc<ResolvedLoadHandle>>;
66
67    /// Returns the ArtifactId for the given LoadHandle, if present.
68    ///
69    /// # Parameters
70    ///
71    /// * `load_handle`: ID allocated by [`Loader`](crate::loader::Loader) to track loading of the artifact.
72    fn artifact_id(
73        &self,
74        load: LoadHandle,
75    ) -> Option<ArtifactId>;
76}
77
78#[derive(Debug)]
79pub struct ResolvedLoadHandle {
80    pub id: LoadHandle,
81    pub direct_load_handle: AtomicU64,
82}
83
84impl PartialEq for ResolvedLoadHandle {
85    fn eq(
86        &self,
87        other: &Self,
88    ) -> bool {
89        // Only need to check the indirect ID
90        self.id == other.id
91    }
92}
93
94impl Eq for ResolvedLoadHandle {}
95
96impl Hash for ResolvedLoadHandle {
97    fn hash<H: Hasher>(
98        &self,
99        state: &mut H,
100    ) {
101        // Only care about hashing the id
102        self.id.hash(state)
103    }
104}
105
106impl ResolvedLoadHandle {
107    pub fn new(
108        id: LoadHandle,
109        resolved_load_handle: LoadHandle,
110    ) -> Arc<Self> {
111        Arc::new(ResolvedLoadHandle {
112            id,
113            direct_load_handle: AtomicU64::new(resolved_load_handle.0),
114        })
115    }
116
117    pub fn new_null_handle() -> Arc<Self> {
118        Arc::new(ResolvedLoadHandle {
119            id: LoadHandle(0),
120            direct_load_handle: AtomicU64::default(),
121        })
122    }
123
124    pub fn direct_load_handle(&self) -> LoadHandle {
125        LoadHandle(self.direct_load_handle.load(Ordering::Relaxed))
126    }
127}
128
129/// Operations on an artifact reference.
130#[derive(Debug)]
131pub enum RefOp {
132    Decrease(LoadHandle),
133    Increase(LoadHandle),
134}
135
136/// Keeps track of whether a handle ref is a strong, weak or "internal" ref
137#[derive(Debug)]
138pub enum HandleRefType {
139    /// Strong references decrement the count on drop
140    Strong(Sender<RefOp>),
141    /// Weak references do nothing on drop.
142    Weak(Sender<RefOp>),
143    /// Internal references do nothing on drop, but turn into Strong references on clone.
144    /// Should only be used for references stored in loaded artifacts to avoid self-referencing
145    Internal(Sender<RefOp>),
146    /// Implementation detail, used when changing state in this enum
147    None,
148}
149
150struct HandleRef {
151    resolved_load_handle: Arc<ResolvedLoadHandle>,
152    ref_type: HandleRefType,
153}
154impl PartialEq for HandleRef {
155    fn eq(
156        &self,
157        other: &Self,
158    ) -> bool {
159        self.resolved_load_handle
160            .id
161            .eq(&other.resolved_load_handle.id)
162    }
163}
164impl Hash for HandleRef {
165    fn hash<H: std::hash::Hasher>(
166        &self,
167        state: &mut H,
168    ) {
169        self.resolved_load_handle.id.hash(state)
170    }
171}
172impl Eq for HandleRef {}
173impl Debug for HandleRef {
174    fn fmt(
175        &self,
176        f: &mut std::fmt::Formatter<'_>,
177    ) -> std::fmt::Result {
178        self.resolved_load_handle.id.fmt(f)
179    }
180}
181
182impl Drop for HandleRef {
183    fn drop(&mut self) {
184        use HandleRefType::*;
185        self.ref_type = match std::mem::replace(&mut self.ref_type, None) {
186            Strong(sender) => {
187                let _ = sender.send(RefOp::Decrease(self.resolved_load_handle.id));
188                Weak(sender)
189            }
190            r => r,
191        };
192    }
193}
194
195impl Clone for HandleRef {
196    fn clone(&self) -> Self {
197        use HandleRefType::*;
198        Self {
199            resolved_load_handle: self.resolved_load_handle.clone(),
200            ref_type: match &self.ref_type {
201                Internal(sender) | Strong(sender) => {
202                    let _ = sender.send(RefOp::Increase(self.resolved_load_handle.id));
203                    Strong(sender.clone())
204                }
205                Weak(sender) => Weak(sender.clone()),
206                None => panic!("unexpected ref type in clone()"),
207            },
208        }
209    }
210}
211
212impl ArtifactHandle for HandleRef {
213    fn resolved_load_handle(&self) -> &Arc<ResolvedLoadHandle> {
214        &self.resolved_load_handle
215    }
216}
217
218/// Handle to an artifact.
219#[derive(Eq)]
220pub struct Handle<T: ?Sized> {
221    handle_ref: HandleRef,
222    marker: PhantomData<T>,
223}
224
225impl<T: ?Sized> PartialEq for Handle<T> {
226    fn eq(
227        &self,
228        other: &Self,
229    ) -> bool {
230        self.handle_ref == other.handle_ref
231    }
232}
233
234impl<T: ?Sized> Clone for Handle<T> {
235    fn clone(&self) -> Self {
236        Self {
237            handle_ref: self.handle_ref.clone(),
238            marker: PhantomData,
239        }
240    }
241}
242
243impl<T: ?Sized> Hash for Handle<T> {
244    fn hash<H: std::hash::Hasher>(
245        &self,
246        state: &mut H,
247    ) {
248        self.handle_ref.hash(state);
249    }
250}
251
252impl<T: ?Sized> Debug for Handle<T> {
253    fn fmt(
254        &self,
255        f: &mut std::fmt::Formatter<'_>,
256    ) -> std::fmt::Result {
257        f.debug_struct("Handle")
258            .field("handle_ref", &self.handle_ref)
259            .finish()
260    }
261}
262
263impl<T: ?Sized> From<GenericHandle> for Handle<T> {
264    fn from(handle: GenericHandle) -> Self {
265        Self {
266            handle_ref: handle.handle_ref,
267            marker: PhantomData,
268        }
269    }
270}
271
272impl<T> Handle<T> {
273    /// Creates a new handle with `HandleRefType::Strong`
274    pub fn new(
275        chan: Sender<RefOp>,
276        resolved_load_handle: Arc<ResolvedLoadHandle>,
277    ) -> Self {
278        Self {
279            handle_ref: HandleRef {
280                resolved_load_handle,
281                ref_type: HandleRefType::Strong(chan),
282            },
283            marker: PhantomData,
284        }
285    }
286
287    /// Creates a new handle with `HandleRefType::Internal`
288    pub(crate) fn new_internal(
289        chan: Sender<RefOp>,
290        resolved_load_handle: Arc<ResolvedLoadHandle>,
291    ) -> Self {
292        Self {
293            handle_ref: HandleRef {
294                resolved_load_handle,
295                ref_type: HandleRefType::Internal(chan),
296            },
297            marker: PhantomData,
298        }
299    }
300
301    pub fn artifact<'a>(
302        &self,
303        storage: &'a impl TypedArtifactStorage<T>,
304    ) -> Option<&'a T> {
305        ArtifactHandle::artifact(self, storage)
306    }
307}
308
309impl<T> ArtifactHandle for Handle<T> {
310    fn resolved_load_handle(&self) -> &Arc<ResolvedLoadHandle> {
311        &self.handle_ref.resolved_load_handle
312    }
313}
314
315/// Handle to an artifact whose type is unknown during loading.
316///
317/// This is returned by `Loader::load_artifact_generic` for artifacts loaded by UUID.
318#[derive(Debug, Clone, PartialEq, Eq, Hash)]
319pub struct GenericHandle {
320    handle_ref: HandleRef,
321}
322
323impl GenericHandle {
324    /// Creates a new handle with `HandleRefType::Strong`
325    pub fn new(
326        chan: Sender<RefOp>,
327        resolved_load_handle: Arc<ResolvedLoadHandle>,
328    ) -> Self {
329        Self {
330            handle_ref: HandleRef {
331                resolved_load_handle,
332                ref_type: HandleRefType::Strong(chan),
333            },
334        }
335    }
336
337    /// Creates a new handle with `HandleRefType::Internal`
338    pub(crate) fn new_internal(
339        chan: Sender<RefOp>,
340        resolved_load_handle: Arc<ResolvedLoadHandle>,
341    ) -> Self {
342        Self {
343            handle_ref: HandleRef {
344                resolved_load_handle,
345                ref_type: HandleRefType::Internal(chan),
346            },
347        }
348    }
349}
350
351impl ArtifactHandle for GenericHandle {
352    fn resolved_load_handle(&self) -> &Arc<ResolvedLoadHandle> {
353        &self.handle_ref.resolved_load_handle
354    }
355}
356
357impl<T: ?Sized> From<Handle<T>> for GenericHandle {
358    fn from(handle: Handle<T>) -> Self {
359        Self {
360            handle_ref: handle.handle_ref,
361        }
362    }
363}
364
365/// Handle to an artifact that does not prevent the artifact from being unloaded.
366///
367/// Weak handles are primarily used when you want to use something that is already loaded.
368///
369/// For example, a strong handle to an artifact may be guaranteed to exist elsewhere in the program,
370/// and so you can simply get and use a weak handle to that artifact in other parts of your code. This
371/// removes reference counting overhead, but also ensures that the system which uses the weak handle
372/// is not in control of when to unload the artifact.
373#[derive(Clone, Eq, Hash, PartialEq, Debug)]
374pub struct WeakHandle {
375    resolved_load_handle: Arc<ResolvedLoadHandle>,
376}
377
378impl WeakHandle {
379    pub fn new(handle: Arc<ResolvedLoadHandle>) -> Self {
380        WeakHandle {
381            resolved_load_handle: handle,
382        }
383    }
384}
385
386impl ArtifactHandle for WeakHandle {
387    fn resolved_load_handle(&self) -> &Arc<ResolvedLoadHandle> {
388        &self.resolved_load_handle
389    }
390}
391
392std::thread_local!(static LOADER: std::cell::RefCell<Option<&'static dyn LoaderInfoProvider>> = RefCell::new(None));
393std::thread_local!(static REFOP_SENDER: std::cell::RefCell<Option<Sender<RefOp>>> = RefCell::new(None));
394
395/// Used to make some limited Loader interactions available to `serde` Serialize/Deserialize
396/// implementations by using thread-local storage. Required to support Serialize/Deserialize of Handle.
397pub struct SerdeContext;
398impl SerdeContext {
399    pub fn with_active<R>(f: impl FnOnce(&dyn LoaderInfoProvider, &Sender<RefOp>) -> R) -> R {
400        //LOADER.with(|l| REFOP_SENDER.with(|r| f(*l, r)))
401        LOADER.with(|loader| {
402            //*loader.borrow_mut() = Some(loader_info_provider);
403            REFOP_SENDER.with(|refop_sender| {
404                (f)(
405                    *loader.borrow().as_ref().unwrap(),
406                    refop_sender.borrow().as_ref().unwrap(),
407                )
408                //*refop_sender.borrow_mut() = Some(sender);
409                //let output = (f)(l, r);
410                //*refop_sender.borrow_mut() = None;
411                //output
412            })
413            //*loader.borrow_mut() = None;
414            //output
415        })
416    }
417
418    pub fn with<T, F>(
419        loader: &dyn LoaderInfoProvider,
420        sender: Sender<RefOp>,
421        f: F,
422    ) -> T
423    where
424        F: FnOnce() -> T,
425    {
426        // The loader lifetime needs to be transmuted to 'static to be able to be stored in thread_local.
427        // This is safe since SerdeContext's lifetime cannot be shorter than the opened scope, and the loader
428        // must live at least as long.
429        let loader_info_provider = unsafe {
430            std::mem::transmute::<&dyn LoaderInfoProvider, &'static dyn LoaderInfoProvider>(loader)
431        };
432
433        LOADER.with(|loader| {
434            *loader.borrow_mut() = Some(loader_info_provider);
435            let output = REFOP_SENDER.with(|refop_sender| {
436                *refop_sender.borrow_mut() = Some(sender);
437                let output = (f)();
438                *refop_sender.borrow_mut() = None;
439                output
440            });
441            *loader.borrow_mut() = None;
442            output
443        })
444
445        // *LOADER.borrow_mut() = Some(loader);
446        // *REFOP_SENDER.borrow_mut() = Some(sender);
447        //
448        //
449        // (*f)();
450        //
451        // *LOADER.borrow_mut() = None;
452        // *REFOP_SENDER.borrow_mut() = None;
453
454        // LOADER.(|x| {
455        //
456        // })
457        //
458        // LOADER.scope(loader, REFOP_SENDER.scope(sender, f)).await
459    }
460}
461
462/// This context can be used to maintain ArtifactId references through a serialize/deserialize cycle
463/// even if the LoadHandles produced are invalid. This is useful when a loader is not
464/// present, such as when processing in the Distill Daemon.
465pub struct DummySerdeContext {
466    maps: RwLock<DummySerdeContextMaps>,
467    current: Mutex<DummySerdeContextCurrent>,
468    ref_sender: Sender<RefOp>,
469    handle_gen: AtomicU64,
470}
471
472struct DummySerdeContextMaps {
473    uuid_to_load: HashMap<ArtifactRef, LoadHandle>,
474    load_to_uuid: HashMap<LoadHandle, ArtifactRef>,
475}
476
477struct DummySerdeContextCurrent {
478    current_serde_dependencies: HashSet<ArtifactRef>,
479    current_serde_artifact: Option<ArtifactId>,
480}
481
482impl DummySerdeContext {
483    pub fn new() -> Self {
484        let (tx, _) = crossbeam_channel::unbounded();
485        Self {
486            maps: RwLock::new(DummySerdeContextMaps {
487                uuid_to_load: HashMap::default(),
488                load_to_uuid: HashMap::default(),
489            }),
490            current: Mutex::new(DummySerdeContextCurrent {
491                current_serde_dependencies: HashSet::new(),
492                current_serde_artifact: None,
493            }),
494            ref_sender: tx,
495            handle_gen: AtomicU64::new(1),
496        }
497    }
498}
499
500impl LoaderInfoProvider for DummySerdeContext {
501    fn resolved_load_handle(
502        &self,
503        artifact_ref: &ArtifactRef,
504    ) -> Option<Arc<ResolvedLoadHandle>> {
505        let mut maps = self.maps.write().unwrap();
506        let maps = &mut *maps;
507        let uuid_to_load = &mut maps.uuid_to_load;
508        let load_to_uuid = &mut maps.load_to_uuid;
509
510        let entry = uuid_to_load.entry(artifact_ref.clone());
511        let handle = entry.or_insert_with(|| {
512            let new_id = self.handle_gen.fetch_add(1, Ordering::Relaxed);
513            let handle = LoadHandle(new_id);
514            load_to_uuid.insert(handle, artifact_ref.clone());
515            handle
516        });
517
518        Some(Arc::new(ResolvedLoadHandle {
519            id: *handle,
520            direct_load_handle: AtomicU64::new(handle.0),
521        }))
522    }
523
524    fn artifact_id(
525        &self,
526        load: LoadHandle,
527    ) -> Option<ArtifactId> {
528        let maps = self.maps.read().unwrap();
529        let maybe_artifact = maps.load_to_uuid.get(&load).cloned();
530        if let Some(artifact_ref) = maybe_artifact.as_ref() {
531            let mut current = self.current.lock().unwrap();
532            if let Some(ref current_serde_id) = current.current_serde_artifact {
533                if ArtifactRef(*current_serde_id) != *artifact_ref
534                    && *artifact_ref != ArtifactRef(ArtifactId::null())
535                {
536                    current
537                        .current_serde_dependencies
538                        .insert(artifact_ref.clone());
539                }
540            }
541        }
542        if let Some(ArtifactRef(uuid)) = maybe_artifact {
543            Some(uuid)
544        } else {
545            None
546        }
547    }
548}
549pub struct DummySerdeContextHandle {
550    dummy: Arc<DummySerdeContext>,
551}
552
553impl Default for DummySerdeContextHandle {
554    fn default() -> Self {
555        DummySerdeContextHandle {
556            dummy: Arc::new(DummySerdeContext::new()),
557        }
558    }
559}
560
561impl DummySerdeContextHandle {
562    pub fn scope<'a, T, F: FnOnce() -> T>(
563        &self,
564        f: F,
565    ) -> T {
566        let sender = self.dummy.ref_sender.clone();
567        let loader = &*self.dummy;
568        SerdeContext::with(loader, sender, f)
569    }
570
571    pub fn resolve_ref(
572        &mut self,
573        artifact_ref: &ArtifactRef,
574        artifact: ArtifactId,
575    ) {
576        let new_ref = ArtifactRef(artifact);
577        let mut maps = self.dummy.maps.write().unwrap();
578        if let Some(handle) = maps.uuid_to_load.get(artifact_ref) {
579            let handle = *handle;
580            maps.load_to_uuid.insert(handle, new_ref.clone());
581            maps.uuid_to_load.insert(new_ref, handle);
582        }
583    }
584
585    /// Begin gathering dependencies for an artifact
586    pub fn begin_serialize_artifact(
587        &mut self,
588        artifact: ArtifactId,
589    ) {
590        let mut current = self.dummy.current.lock().unwrap();
591        if current.current_serde_artifact.is_some() {
592            panic!("begin_serialize_artifact when current_serde_artifact is already set");
593        }
594        current.current_serde_artifact = Some(artifact);
595    }
596
597    /// Finish gathering dependencies for an artifact
598    pub fn end_serialize_artifact(
599        &mut self,
600        _artifact: ArtifactId,
601    ) -> HashSet<ArtifactRef> {
602        let mut current = self.dummy.current.lock().unwrap();
603        if current.current_serde_artifact.is_none() {
604            panic!("end_serialize_artifact when current_serde_artifact is not set");
605        }
606        current.current_serde_artifact = None;
607        std::mem::take(&mut current.current_serde_dependencies)
608    }
609}
610
611/// Register this context with ArtifactDaemon to add serde support for Handle.
612// pub struct HandleSerdeContextProvider;
613// impl crate::importer_context::ImporterContext for HandleSerdeContextProvider {
614//     fn handle(&self) -> Box<dyn crate::importer_context::ImporterContextHandle> {
615//         let dummy = Arc::new(DummySerdeContext::new());
616//         Box::new(DummySerdeContextHandle { dummy })
617//     }
618// }
619
620fn serialize_handle<S>(
621    load: LoadHandle,
622    serializer: S,
623) -> Result<S::Ok, S::Error>
624where
625    S: ser::Serializer,
626{
627    SerdeContext::with_active(|loader, _| {
628        use ser::SerializeSeq;
629        let uuid_bytes: uuid::Bytes = *loader
630            .artifact_id(load)
631            .unwrap_or_default()
632            .as_uuid()
633            .as_bytes();
634        let mut seq = serializer.serialize_seq(Some(uuid_bytes.len()))?;
635        for element in &uuid_bytes {
636            seq.serialize_element(element)?;
637        }
638        seq.end()
639    })
640}
641impl<T> Serialize for Handle<T> {
642    fn serialize<S>(
643        &self,
644        serializer: S,
645    ) -> Result<S::Ok, S::Error>
646    where
647        S: ser::Serializer,
648    {
649        serialize_handle(self.handle_ref.resolved_load_handle.id, serializer)
650    }
651}
652impl Serialize for GenericHandle {
653    fn serialize<S>(
654        &self,
655        serializer: S,
656    ) -> Result<S::Ok, S::Error>
657    where
658        S: ser::Serializer,
659    {
660        serialize_handle(self.handle_ref.resolved_load_handle.id, serializer)
661    }
662}
663
664fn get_handle_ref(artifact_ref: ArtifactRef) -> (Arc<ResolvedLoadHandle>, Sender<RefOp>) {
665    SerdeContext::with_active(|loader, sender| {
666        let handle = if artifact_ref == ArtifactRef(ArtifactId::default()) {
667            ResolvedLoadHandle::new_null_handle()
668        } else {
669            loader
670                .resolved_load_handle(&artifact_ref)
671                .unwrap_or_else(|| panic!("Handle for ArtifactId {:?} was not present when deserializing a Handle. This indicates missing dependency metadata, and can be caused by dependency cycles.", artifact_ref))
672        };
673        (handle, sender.clone())
674    })
675}
676
677impl<'de, T> Deserialize<'de> for Handle<T> {
678    fn deserialize<D>(deserializer: D) -> Result<Handle<T>, D::Error>
679    where
680        D: de::Deserializer<'de>,
681    {
682        let artifact_ref = if deserializer.is_human_readable() {
683            deserializer.deserialize_any(ArtifactRefVisitor)?
684        } else {
685            deserializer.deserialize_seq(ArtifactRefVisitor)?
686        };
687        let (handle, sender) = get_handle_ref(artifact_ref);
688        Ok(Handle::new_internal(sender, handle))
689    }
690}
691
692impl<'de> Deserialize<'de> for GenericHandle {
693    fn deserialize<D>(deserializer: D) -> Result<GenericHandle, D::Error>
694    where
695        D: de::Deserializer<'de>,
696    {
697        let artifact_ref = if deserializer.is_human_readable() {
698            deserializer.deserialize_any(ArtifactRefVisitor)?
699        } else {
700            deserializer.deserialize_seq(ArtifactRefVisitor)?
701        };
702        let (handle, sender) = get_handle_ref(artifact_ref);
703        Ok(GenericHandle::new_internal(sender, handle))
704    }
705}
706
707struct ArtifactRefVisitor;
708
709impl<'de> de::Visitor<'de> for ArtifactRefVisitor {
710    type Value = ArtifactRef;
711
712    fn expecting(
713        &self,
714        formatter: &mut std::fmt::Formatter<'_>,
715    ) -> std::fmt::Result {
716        formatter.write_str("an array of 16 u8")
717    }
718
719    fn visit_newtype_struct<D>(
720        self,
721        deserializer: D,
722    ) -> Result<Self::Value, D::Error>
723    where
724        D: de::Deserializer<'de>,
725    {
726        deserializer.deserialize_seq(self)
727    }
728
729    fn visit_seq<A>(
730        self,
731        mut seq: A,
732    ) -> Result<Self::Value, A::Error>
733    where
734        A: de::SeqAccess<'de>,
735    {
736        use de::Error;
737        let mut uuid: [u8; 16] = Default::default();
738        for (i, uuid_byte) in uuid.iter_mut().enumerate() {
739            if let Some(byte) = seq.next_element::<u8>()? {
740                *uuid_byte = byte;
741            } else {
742                return Err(A::Error::custom(format!(
743                    "expected byte at element {} when deserializing handle",
744                    i
745                )));
746            }
747        }
748        if seq.next_element::<u8>()?.is_some() {
749            return Err(A::Error::custom(
750                "too many elements when deserializing handle",
751            ));
752        }
753        Ok(ArtifactRef(ArtifactId::from_uuid(Uuid::from_bytes(uuid))))
754    }
755
756    fn visit_str<E>(
757        self,
758        v: &str,
759    ) -> Result<Self::Value, E>
760    where
761        E: de::Error,
762    {
763        if let Ok(uuid) = Uuid::parse_str(v) {
764            Ok(ArtifactRef(ArtifactId::from_uuid(uuid)))
765        } else {
766            Err(E::custom(format!("failed to parse Handle string")))
767        }
768    }
769
770    fn visit_bytes<E>(
771        self,
772        v: &[u8],
773    ) -> Result<Self::Value, E>
774    where
775        E: de::Error,
776    {
777        if v.len() != 16 {
778            Err(E::custom(format!(
779                "byte array len == {}, expected {}",
780                v.len(),
781                16
782            )))
783        } else {
784            let mut a = <[u8; 16]>::default();
785            a.copy_from_slice(v);
786            Ok(ArtifactRef(ArtifactId::from_uuid(Uuid::from_bytes(a))))
787        }
788    }
789}
790
791/// Implementors of [`crate::storage::ArtifactStorage`] can implement this trait to enable convenience
792/// functions on the common [`ArtifactHandle`] trait, which is implemented by all handle types.
793pub trait TypedArtifactStorage<A> {
794    /// Returns the artifact for the given handle, or `None` if has not completed loading.
795    ///
796    /// # Parameters
797    ///
798    /// * `handle`: Handle of the artifact.
799    ///
800    /// # Type Parameters
801    ///
802    /// * `T`: Artifact handle type.
803    fn get<T: ArtifactHandle>(
804        &self,
805        handle: &T,
806    ) -> Option<&A>;
807}
808
809#[derive(Debug, Copy, Clone, PartialEq, Eq)]
810pub enum LoadState {
811    // Not loaded, and we haven't started trying to load it. Ref count > 0 implies we want to start
812    // loading.
813    Unloaded,
814    // Metadata request is in flight
815    WaitingForMetadata,
816    // We've incremented ref counts for dependencies, but they aren't loaded yet
817    WaitingForDependencies,
818    // Dependencies are loaded, and we have requested the data required to load this artifact
819    WaitingForData,
820    // Data has been passed off to end-user's loader
821    Loading,
822    // The engine finished loading the artifact and it is available to the game.
823    Loaded,
824}
825
826// This allows a handle in hydrate_base to get information from the loader which may be in hydrate_loader
827// or some other loader implementation
828pub trait LoadStateProvider {
829    fn load_state(
830        &self,
831        load_handle: &Arc<ResolvedLoadHandle>,
832    ) -> LoadState;
833    fn artifact_id(
834        &self,
835        load_handle: &Arc<ResolvedLoadHandle>,
836    ) -> ArtifactId;
837}
838
839/// The contract of an artifact handle.
840///
841/// There are two types of artifact handles:
842///
843/// * **Typed -- `Handle<T>`:** When the artifact's type is known when loading.
844/// * **Generic -- `GenericHandle`:** When only the artifact's UUID is known when loading.
845pub trait ArtifactHandle {
846    /// Returns the load status of the artifact.
847    ///
848    /// # Parameters
849    ///
850    /// * `loader`: Loader that is loading the artifact.
851    ///
852    /// # Type Parameters
853    ///
854    /// * `L`: Artifact loader type.
855    fn load_state<T: LoadStateProvider>(
856        &self,
857        loader: &T,
858    ) -> LoadState {
859        loader.load_state(self.resolved_load_handle())
860    }
861
862    fn artifact_id<T: LoadStateProvider>(
863        &self,
864        loader: &T,
865    ) -> ArtifactId {
866        loader.artifact_id(self.resolved_load_handle())
867    }
868
869    /// Returns an immutable reference to the artifact if it is committed.
870    ///
871    /// # Parameters
872    ///
873    /// * `storage`: Artifact storage.
874    fn artifact<'a, T, S: TypedArtifactStorage<T>>(
875        &self,
876        storage: &'a S,
877    ) -> Option<&'a T>
878    where
879        Self: Sized,
880    {
881        storage.get(self)
882    }
883
884    /// Downgrades this handle into a `WeakHandle`.
885    ///
886    /// Be aware that if there are no longer any strong handles to the artifact, then the underlying
887    /// artifact may be freed at any time.
888    fn downgrade(&self) -> WeakHandle {
889        WeakHandle::new(self.resolved_load_handle().clone())
890    }
891
892    fn resolved_load_handle(&self) -> &Arc<ResolvedLoadHandle>;
893
894    /// Returns the `LoadHandle` of this artifact handle.
895    fn load_handle(&self) -> LoadHandle {
896        self.resolved_load_handle().id
897    }
898
899    fn direct_load_handle(&self) -> LoadHandle {
900        self.resolved_load_handle().direct_load_handle()
901    }
902}
903
904pub fn make_handle_within_serde_context<T>(uuid: ArtifactId) -> Handle<T> {
905    SerdeContext::with_active(|loader_info_provider, ref_op_sender| {
906        let load_handle = loader_info_provider
907            .resolved_load_handle(&ArtifactRef(uuid))
908            .unwrap();
909        Handle::<T>::new(ref_op_sender.clone(), load_handle)
910    })
911}