makepad_stitch/
extern_val.rs

1use crate::{
2    decode::{Decode, DecodeError, Decoder},
3    func::{Func, FuncType, UnguardedFunc},
4    global::{Global, GlobalType, UnguardedGlobal},
5    mem::{Mem, MemType, UnguardedMem},
6    store::{Store, StoreId},
7    table::{Table, TableType, UnguardedTable},
8};
9
10/// A Wasm entity that can be imported or exported.
11#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
12pub enum ExternVal {
13    Func(Func),
14    Table(Table),
15    Memory(Mem),
16    Global(Global),
17}
18
19impl ExternVal {
20    /// Returns the [`ExternType`] of this [`ExternVal`].
21    pub fn type_(self, store: &Store) -> ExternType {
22        match self {
23            Self::Func(func) => ExternType::Func(func.type_(store).clone()),
24            Self::Table(table) => ExternType::Table(table.type_(store)),
25            Self::Memory(mem) => ExternType::Mem(mem.type_(store)),
26            Self::Global(global) => ExternType::Global(global.type_(store)),
27        }
28    }
29
30    /// Returns `true` if this [`ExternVal`] is a [`Func`].
31    pub fn is_func(self) -> bool {
32        self.to_func().is_some()
33    }
34
35    /// Returns `true` if this [`ExternVal`] is a [`Table`].
36    pub fn is_table(self) -> bool {
37        self.to_table().is_some()
38    }
39
40    /// Returns `true` if this [`ExternVal`] is a [`Mem`].
41    pub fn is_mem(self) -> bool {
42        self.to_mem().is_some()
43    }
44
45    /// Returns `true` if this [`ExternVal`] is a [`Global`].
46    pub fn is_global(self) -> bool {
47        self.to_global().is_some()
48    }
49
50    /// Converts this [`ExternVal`] to a [`Func`], if it is one.
51    pub fn to_func(self) -> Option<Func> {
52        match self {
53            Self::Func(func) => Some(func),
54            _ => None,
55        }
56    }
57
58    /// Converts this [`ExternVal`] to a [`Table`], if it is one.
59    pub fn to_table(self) -> Option<Table> {
60        match self {
61            Self::Table(table) => Some(table),
62            _ => None,
63        }
64    }
65
66    /// Converts this [`ExternVal`] to a [`Mem`], if it is one.
67    pub fn to_mem(self) -> Option<Mem> {
68        match self {
69            Self::Memory(mem) => Some(mem),
70            _ => None,
71        }
72    }
73
74    /// Converts this [`ExternVal`] to a [`Global`], if it is one.
75    pub fn to_global(self) -> Option<Global> {
76        match self {
77            Self::Global(global) => Some(global),
78            _ => None,
79        }
80    }
81
82    /// Converts the given [`UnguardedExternVal`] to an [`ExternVal`].
83    ///
84    /// # Safety
85    ///
86    /// Any [`UnguardedHandle`] in the given [`UnguardedExternVal`] must be owned by the [`Store`]
87    /// with the given [`StoreId`].
88    pub(crate) unsafe fn from_unguarded(val: UnguardedExternVal, store_id: StoreId) -> Self {
89        match val {
90            UnguardedExternVal::Func(func) => Func::from_unguarded(func, store_id).into(),
91            UnguardedExternVal::Table(table) => Table::from_unguarded(table, store_id).into(),
92            UnguardedExternVal::Mem(mem) => Mem::from_unguarded(mem, store_id).into(),
93            UnguardedExternVal::Global(global) => Global::from_unguarded(global, store_id).into(),
94        }
95    }
96
97    /// Converts this [`ExternVal`] to an [`UnguardedExternVal`].
98    ///
99    /// # Panics
100    ///
101    /// Panics if any [`Handle`] in this [`ExternVal`] is not owned by the [`Store`] with the given
102    /// [`StoreId`].
103    pub(crate) fn to_unguarded(self, store_id: StoreId) -> UnguardedExternVal {
104        match self {
105            Self::Func(func) => func.to_unguarded(store_id).into(),
106            Self::Table(table) => table.to_unguarded(store_id).into(),
107            Self::Memory(mem) => mem.to_unguarded(store_id).into(),
108            Self::Global(global) => global.to_unguarded(store_id).into(),
109        }
110    }
111}
112
113impl From<Func> for ExternVal {
114    fn from(func: Func) -> Self {
115        Self::Func(func)
116    }
117}
118
119impl From<Table> for ExternVal {
120    fn from(table: Table) -> Self {
121        Self::Table(table)
122    }
123}
124
125impl From<Mem> for ExternVal {
126    fn from(memory: Mem) -> Self {
127        Self::Memory(memory)
128    }
129}
130
131impl From<Global> for ExternVal {
132    fn from(global: Global) -> Self {
133        Self::Global(global)
134    }
135}
136
137#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
138pub(crate) enum UnguardedExternVal {
139    Func(UnguardedFunc),
140    Table(UnguardedTable),
141    Mem(UnguardedMem),
142    Global(UnguardedGlobal),
143}
144
145impl From<UnguardedFunc> for UnguardedExternVal {
146    fn from(func: UnguardedFunc) -> Self {
147        Self::Func(func)
148    }
149}
150
151impl From<UnguardedTable> for UnguardedExternVal {
152    fn from(table: UnguardedTable) -> Self {
153        Self::Table(table)
154    }
155}
156
157impl From<UnguardedMem> for UnguardedExternVal {
158    fn from(mem: UnguardedMem) -> Self {
159        Self::Mem(mem)
160    }
161}
162
163impl From<UnguardedGlobal> for UnguardedExternVal {
164    fn from(global: UnguardedGlobal) -> Self {
165        Self::Global(global)
166    }
167}
168
169/// An descriptor for an [`ExternVal`].
170///
171/// This is just like an [`ExternVal`], except that each entity is represented by an index into
172/// the respective section of a module.
173#[derive(Clone, Copy, Debug)]
174pub(crate) enum ExternValDesc {
175    Func(u32),
176    Table(u32),
177    Memory(u32),
178    Global(u32),
179}
180
181impl Decode for ExternValDesc {
182    fn decode(decoder: &mut Decoder<'_>) -> Result<Self, DecodeError> {
183        match decoder.read_byte()? {
184            0x00 => Ok(Self::Func(decoder.decode()?)),
185            0x01 => Ok(Self::Table(decoder.decode()?)),
186            0x02 => Ok(Self::Memory(decoder.decode()?)),
187            0x03 => Ok(Self::Global(decoder.decode()?)),
188            _ => Err(DecodeError::new("malformed external value descriptor")),
189        }
190    }
191}
192
193/// The type of an [`ExternVal`].
194#[derive(Clone, Debug, Eq, Hash, PartialEq)]
195pub enum ExternType {
196    Func(FuncType),
197    Table(TableType),
198    Mem(MemType),
199    Global(GlobalType),
200}
201
202impl ExternType {
203    /// Returns `true` if this [`ExternType`] is a [`FuncType`].
204    pub fn is_func(self) -> bool {
205        self.to_func().is_some()
206    }
207
208    /// Returns `true` if this [`ExternType`] is a [`TableType`].
209    pub fn is_table(self) -> bool {
210        self.to_table().is_some()
211    }
212
213    /// Returns `true` if this [`ExternType`] is a [`MemType`].
214    pub fn is_mem(self) -> bool {
215        self.to_mem().is_some()
216    }
217
218    /// Returns `true` if this [`ExternType`] is a [`GlobalType`].
219    pub fn is_global(self) -> bool {
220        self.to_global().is_some()
221    }
222
223    /// Returns the underlying [`FuncType`] if this [`ExternType`] is a [`FuncType`].
224    pub fn to_func(self) -> Option<FuncType> {
225        match self {
226            Self::Func(func_type) => Some(func_type),
227            _ => None,
228        }
229    }
230
231    /// Converts this [`ExternType`] to a [`TableType`], if it is one.
232    pub fn to_table(self) -> Option<TableType> {
233        match self {
234            Self::Table(table_type) => Some(table_type),
235            _ => None,
236        }
237    }
238
239    /// Converts this [`ExternType`] to a [`MemType`], if it is one.
240    pub fn to_mem(self) -> Option<MemType> {
241        match self {
242            Self::Mem(mem_type) => Some(mem_type),
243            _ => None,
244        }
245    }
246
247    /// Converts this [`ExternType`] to a [`GlobalType`], if it is one.
248    pub fn to_global(self) -> Option<GlobalType> {
249        match self {
250            Self::Global(global_type) => Some(global_type),
251            _ => None,
252        }
253    }
254}
255
256impl From<FuncType> for ExternType {
257    fn from(type_: FuncType) -> Self {
258        Self::Func(type_)
259    }
260}
261
262impl From<TableType> for ExternType {
263    fn from(type_: TableType) -> Self {
264        Self::Table(type_)
265    }
266}
267
268impl From<MemType> for ExternType {
269    fn from(type_: MemType) -> Self {
270        Self::Mem(type_)
271    }
272}
273
274impl From<GlobalType> for ExternType {
275    fn from(type_: GlobalType) -> Self {
276        Self::Global(type_)
277    }
278}
279
280/// A descriptor for an [`ExternType`].
281///
282/// This is just like an [`ExternType`], except that function types are represented by an index
283/// into the type section of a module.
284#[derive(Clone, Copy, Debug)]
285pub(crate) enum ExternTypeDesc {
286    Func(u32),
287    Table(TableType),
288    Memory(MemType),
289    Global(GlobalType),
290}
291
292impl Decode for ExternTypeDesc {
293    fn decode(decoder: &mut Decoder<'_>) -> Result<Self, DecodeError> {
294        match decoder.read_byte()? {
295            0x00 => Ok(ExternTypeDesc::Func(decoder.decode()?)),
296            0x01 => Ok(ExternTypeDesc::Table(decoder.decode()?)),
297            0x02 => Ok(ExternTypeDesc::Memory(decoder.decode()?)),
298            0x03 => Ok(ExternTypeDesc::Global(decoder.decode()?)),
299            _ => Err(DecodeError::new("malformed external type descriptor"))?,
300        }
301    }
302}