makepad_stitch/
ref_.rs

1use crate::{
2    decode::{Decode, DecodeError, Decoder},
3    extern_ref::{ExternRef, UnguardedExternRef},
4    func_ref::{FuncRef, UnguardedFuncRef},
5    store::StoreId,
6};
7
8/// A Wasm reference.
9#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
10pub enum Ref {
11    FuncRef(FuncRef),
12    ExternRef(ExternRef),
13}
14
15impl Ref {
16    /// Returns a null [`Ref`] of the given [`RefType`].
17    pub fn null(type_: RefType) -> Self {
18        match type_ {
19            RefType::FuncRef => FuncRef::null().into(),
20            RefType::ExternRef => ExternRef::null().into(),
21        }
22    }
23
24    /// Returns the [`RefType`] of this [`Ref`].
25    pub fn type_(self) -> RefType {
26        match self {
27            Ref::FuncRef(_) => RefType::FuncRef,
28            Ref::ExternRef(_) => RefType::ExternRef,
29        }
30    }
31
32    /// Returns `true` if this [`Ref`] is a [`FuncRef`].
33    pub fn is_func_ref(self) -> bool {
34        self.to_func_ref().is_some()
35    }
36
37    /// Returns `true` if this [`Ref`] is an [`ExternRef`].
38    pub fn is_extern_ref(self) -> bool {
39        self.to_extern_ref().is_some()
40    }
41
42    /// Converts this [`Ref`] to a [`FuncRef`], if it is one.
43    pub fn to_func_ref(self) -> Option<FuncRef> {
44        match self {
45            Ref::FuncRef(val) => Some(val),
46            _ => None,
47        }
48    }
49
50    /// Converts this [`Ref`] to an [`ExternRef`], if it is one.
51    pub fn to_extern_ref(self) -> Option<ExternRef> {
52        match self {
53            Ref::ExternRef(val) => Some(val),
54            _ => None,
55        }
56    }
57
58    /// Converts the given [`UnguardedRef`] to a [`Ref`].
59    ///
60    /// # Safety
61    ///
62    /// The [`UnguardedRef`] must be owned by the [`Store`] with the given [`StoreId`].
63    pub(crate) unsafe fn from_unguarded(val: UnguardedRef, store_id: StoreId) -> Self {
64        match val {
65            UnguardedRef::FuncRef(val) => FuncRef::from_unguarded(val, store_id).into(),
66            UnguardedRef::ExternRef(val) => ExternRef::from_unguarded(val, store_id).into(),
67        }
68    }
69
70    /// Converts this [`Ref`] to an [`UnguardedRef`].
71    ///
72    /// # Panics
73    ///
74    /// This [`Ref`] is not owned by the [`Store`] with the given [`StoreId`].
75    pub(crate) fn to_unguarded(self, store_id: StoreId) -> UnguardedRef {
76        match self {
77            Ref::FuncRef(val) => val.to_unguarded(store_id).into(),
78            Ref::ExternRef(val) => val.to_unguarded(store_id).into(),
79        }
80    }
81}
82
83impl From<FuncRef> for Ref {
84    fn from(val: FuncRef) -> Self {
85        Ref::FuncRef(val)
86    }
87}
88
89impl From<ExternRef> for Ref {
90    fn from(val: ExternRef) -> Self {
91        Ref::ExternRef(val)
92    }
93}
94
95/// An unguarded [`Ref`].
96#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
97pub(crate) enum UnguardedRef {
98    FuncRef(UnguardedFuncRef),
99    ExternRef(UnguardedExternRef),
100}
101
102impl From<UnguardedFuncRef> for UnguardedRef {
103    fn from(val: UnguardedFuncRef) -> Self {
104        UnguardedRef::FuncRef(val)
105    }
106}
107
108impl From<UnguardedExternRef> for UnguardedRef {
109    fn from(val: UnguardedExternRef) -> Self {
110        UnguardedRef::ExternRef(val)
111    }
112}
113
114/// The type of a [`Ref`].
115#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
116pub enum RefType {
117    FuncRef,
118    ExternRef,
119}
120
121impl Decode for RefType {
122    fn decode(decoder: &mut Decoder<'_>) -> Result<Self, DecodeError> {
123        match decoder.read_byte()? {
124            0x6F => Ok(Self::ExternRef),
125            0x70 => Ok(Self::FuncRef),
126            _ => Err(DecodeError::new("malformed reference type")),
127        }
128    }
129}