wasmtime/runtime/
externals.rs

1use crate::store::StoreOpaque;
2use crate::{AsContext, Engine, ExternType, Func, Memory, SharedMemory};
3
4mod global;
5mod table;
6mod tag;
7
8pub use global::Global;
9pub use table::Table;
10pub use tag::Tag;
11
12// Externals
13
14/// An external item to a WebAssembly module, or a list of what can possibly be
15/// exported from a wasm module.
16///
17/// This is both returned from [`Instance::exports`](crate::Instance::exports)
18/// as well as required by [`Instance::new`](crate::Instance::new). In other
19/// words, this is the type of extracted values from an instantiated module, and
20/// it's also used to provide imported values when instantiating a module.
21#[derive(Clone, Debug)]
22pub enum Extern {
23    /// A WebAssembly `func` which can be called.
24    Func(Func),
25    /// A WebAssembly `global` which acts like a `Cell<T>` of sorts, supporting
26    /// `get` and `set` operations.
27    Global(Global),
28    /// A WebAssembly `table` which is an array of `Val` reference types.
29    Table(Table),
30    /// A WebAssembly linear memory.
31    Memory(Memory),
32    /// A WebAssembly shared memory; these are handled separately from
33    /// [`Memory`].
34    SharedMemory(SharedMemory),
35    /// A WebAssembly exception or control tag which can be referenced
36    /// when raising an exception or stack switching.
37    Tag(Tag),
38}
39
40impl Extern {
41    /// Returns the underlying `Func`, if this external is a function.
42    ///
43    /// Returns `None` if this is not a function.
44    pub fn into_func(self) -> Option<Func> {
45        match self {
46            Extern::Func(func) => Some(func),
47            _ => None,
48        }
49    }
50
51    /// Returns the underlying `Global`, if this external is a global.
52    ///
53    /// Returns `None` if this is not a global.
54    pub fn into_global(self) -> Option<Global> {
55        match self {
56            Extern::Global(global) => Some(global),
57            _ => None,
58        }
59    }
60
61    /// Returns the underlying `Table`, if this external is a table.
62    ///
63    /// Returns `None` if this is not a table.
64    pub fn into_table(self) -> Option<Table> {
65        match self {
66            Extern::Table(table) => Some(table),
67            _ => None,
68        }
69    }
70
71    /// Returns the underlying `Memory`, if this external is a memory.
72    ///
73    /// Returns `None` if this is not a memory.
74    pub fn into_memory(self) -> Option<Memory> {
75        match self {
76            Extern::Memory(memory) => Some(memory),
77            _ => None,
78        }
79    }
80
81    /// Returns the underlying `SharedMemory`, if this external is a shared
82    /// memory.
83    ///
84    /// Returns `None` if this is not a shared memory.
85    pub fn into_shared_memory(self) -> Option<SharedMemory> {
86        match self {
87            Extern::SharedMemory(memory) => Some(memory),
88            _ => None,
89        }
90    }
91
92    /// Returns the underlying `Tag`, if this external is a tag.
93    ///
94    /// Returns `None` if this is not a tag.
95    pub fn into_tag(self) -> Option<Tag> {
96        match self {
97            Extern::Tag(tag) => Some(tag),
98            _ => None,
99        }
100    }
101
102    /// Returns the type associated with this `Extern`.
103    ///
104    /// The `store` argument provided must own this `Extern` and is used to look
105    /// up type information.
106    ///
107    /// # Panics
108    ///
109    /// Panics if this item does not belong to the `store` provided.
110    pub fn ty(&self, store: impl AsContext) -> ExternType {
111        let store = store.as_context();
112        match self {
113            Extern::Func(ft) => ExternType::Func(ft.ty(store)),
114            Extern::Memory(ft) => ExternType::Memory(ft.ty(store)),
115            Extern::SharedMemory(ft) => ExternType::Memory(ft.ty()),
116            Extern::Table(tt) => ExternType::Table(tt.ty(store)),
117            Extern::Global(gt) => ExternType::Global(gt.ty(store)),
118            Extern::Tag(tt) => ExternType::Tag(tt.ty(store)),
119        }
120    }
121
122    pub(crate) unsafe fn from_wasmtime_export(
123        wasmtime_export: crate::runtime::vm::Export,
124        store: &mut StoreOpaque,
125    ) -> Extern {
126        match wasmtime_export {
127            crate::runtime::vm::Export::Function(f) => {
128                Extern::Func(Func::from_wasmtime_function(f, store))
129            }
130            crate::runtime::vm::Export::Memory(m) => {
131                if m.memory.shared {
132                    Extern::SharedMemory(SharedMemory::from_wasmtime_memory(m, store))
133                } else {
134                    Extern::Memory(Memory::from_wasmtime_memory(m, store))
135                }
136            }
137            crate::runtime::vm::Export::Global(g) => {
138                Extern::Global(Global::from_wasmtime_global(g, store))
139            }
140            crate::runtime::vm::Export::Table(t) => {
141                Extern::Table(Table::from_wasmtime_table(t, store))
142            }
143            crate::runtime::vm::Export::Tag(t) => Extern::Tag(Tag::from_wasmtime_tag(t, store)),
144        }
145    }
146
147    pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool {
148        match self {
149            Extern::Func(f) => f.comes_from_same_store(store),
150            Extern::Global(g) => store.store_data().contains(g.0),
151            Extern::Memory(m) => m.comes_from_same_store(store),
152            Extern::SharedMemory(m) => Engine::same(m.engine(), store.engine()),
153            Extern::Table(t) => store.store_data().contains(t.0),
154            Extern::Tag(t) => store.store_data().contains(t.0),
155        }
156    }
157}
158
159impl From<Func> for Extern {
160    fn from(r: Func) -> Self {
161        Extern::Func(r)
162    }
163}
164
165impl From<Global> for Extern {
166    fn from(r: Global) -> Self {
167        Extern::Global(r)
168    }
169}
170
171impl From<Memory> for Extern {
172    fn from(r: Memory) -> Self {
173        Extern::Memory(r)
174    }
175}
176
177impl From<SharedMemory> for Extern {
178    fn from(r: SharedMemory) -> Self {
179        Extern::SharedMemory(r)
180    }
181}
182
183impl From<Table> for Extern {
184    fn from(r: Table) -> Self {
185        Extern::Table(r)
186    }
187}
188
189impl From<Tag> for Extern {
190    fn from(t: Tag) -> Self {
191        Extern::Tag(t)
192    }
193}
194
195// Exports
196
197/// An exported WebAssembly value.
198///
199/// This type is primarily accessed from the
200/// [`Instance::exports`](crate::Instance::exports) accessor and describes what
201/// names and items are exported from a wasm instance.
202#[derive(Clone)]
203pub struct Export<'instance> {
204    /// The name of the export.
205    name: &'instance str,
206
207    /// The definition of the export.
208    definition: Extern,
209}
210
211impl<'instance> Export<'instance> {
212    /// Creates a new export which is exported with the given `name` and has the
213    /// given `definition`.
214    pub(crate) fn new(name: &'instance str, definition: Extern) -> Export<'instance> {
215        Export { name, definition }
216    }
217
218    /// Returns the name by which this export is known.
219    pub fn name(&self) -> &'instance str {
220        self.name
221    }
222
223    /// Return the `ExternType` of this export.
224    ///
225    /// # Panics
226    ///
227    /// Panics if `store` does not own this `Extern`.
228    pub fn ty(&self, store: impl AsContext) -> ExternType {
229        self.definition.ty(store)
230    }
231
232    /// Consume this `Export` and return the contained `Extern`.
233    pub fn into_extern(self) -> Extern {
234        self.definition
235    }
236
237    /// Consume this `Export` and return the contained `Func`, if it's a function,
238    /// or `None` otherwise.
239    pub fn into_func(self) -> Option<Func> {
240        self.definition.into_func()
241    }
242
243    /// Consume this `Export` and return the contained `Table`, if it's a table,
244    /// or `None` otherwise.
245    pub fn into_table(self) -> Option<Table> {
246        self.definition.into_table()
247    }
248
249    /// Consume this `Export` and return the contained `Memory`, if it's a memory,
250    /// or `None` otherwise.
251    pub fn into_memory(self) -> Option<Memory> {
252        self.definition.into_memory()
253    }
254
255    /// Consume this `Export` and return the contained `Global`, if it's a global,
256    /// or `None` otherwise.
257    pub fn into_global(self) -> Option<Global> {
258        self.definition.into_global()
259    }
260
261    /// Consume this `Export` and return the contained `Tag`, if it's a tag,
262    /// or `None` otherwise.
263    pub fn into_tag(self) -> Option<Tag> {
264        self.definition.into_tag()
265    }
266}