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    #[inline]
45    pub fn into_func(self) -> Option<Func> {
46        match self {
47            Extern::Func(func) => Some(func),
48            _ => None,
49        }
50    }
51
52    /// Returns the underlying `Global`, if this external is a global.
53    ///
54    /// Returns `None` if this is not a global.
55    #[inline]
56    pub fn into_global(self) -> Option<Global> {
57        match self {
58            Extern::Global(global) => Some(global),
59            _ => None,
60        }
61    }
62
63    /// Returns the underlying `Table`, if this external is a table.
64    ///
65    /// Returns `None` if this is not a table.
66    #[inline]
67    pub fn into_table(self) -> Option<Table> {
68        match self {
69            Extern::Table(table) => Some(table),
70            _ => None,
71        }
72    }
73
74    /// Returns the underlying `Memory`, if this external is a memory.
75    ///
76    /// Returns `None` if this is not a memory.
77    #[inline]
78    pub fn into_memory(self) -> Option<Memory> {
79        match self {
80            Extern::Memory(memory) => Some(memory),
81            _ => None,
82        }
83    }
84
85    /// Returns the underlying `SharedMemory`, if this external is a shared
86    /// memory.
87    ///
88    /// Returns `None` if this is not a shared memory.
89    #[inline]
90    pub fn into_shared_memory(self) -> Option<SharedMemory> {
91        match self {
92            Extern::SharedMemory(memory) => Some(memory),
93            _ => None,
94        }
95    }
96
97    /// Returns the underlying `Tag`, if this external is a tag.
98    ///
99    /// Returns `None` if this is not a tag.
100    #[inline]
101    pub fn into_tag(self) -> Option<Tag> {
102        match self {
103            Extern::Tag(tag) => Some(tag),
104            _ => None,
105        }
106    }
107
108    /// Returns the type associated with this `Extern`.
109    ///
110    /// The `store` argument provided must own this `Extern` and is used to look
111    /// up type information.
112    ///
113    /// # Panics
114    ///
115    /// Panics if this item does not belong to the `store` provided.
116    pub fn ty(&self, store: impl AsContext) -> ExternType {
117        let store = store.as_context();
118        match self {
119            Extern::Func(ft) => ExternType::Func(ft.ty(store)),
120            Extern::Memory(ft) => ExternType::Memory(ft.ty(store)),
121            Extern::SharedMemory(ft) => ExternType::Memory(ft.ty()),
122            Extern::Table(tt) => ExternType::Table(tt.ty(store)),
123            Extern::Global(gt) => ExternType::Global(gt.ty(store)),
124            Extern::Tag(tt) => ExternType::Tag(tt.ty(store)),
125        }
126    }
127
128    pub(crate) fn from_wasmtime_export(
129        wasmtime_export: crate::runtime::vm::Export,
130        store: &StoreOpaque,
131    ) -> Extern {
132        match wasmtime_export {
133            crate::runtime::vm::Export::Function(f) => Extern::Func(f),
134            crate::runtime::vm::Export::Memory(m) => Extern::Memory(m),
135            crate::runtime::vm::Export::SharedMemory(m, _) => {
136                Extern::SharedMemory(crate::SharedMemory::from_raw(m, store.engine().clone()))
137            }
138            crate::runtime::vm::Export::Global(g) => Extern::Global(g),
139            crate::runtime::vm::Export::Table(t) => Extern::Table(t),
140            crate::runtime::vm::Export::Tag(t) => Extern::Tag(t),
141        }
142    }
143
144    pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool {
145        match self {
146            Extern::Func(f) => f.comes_from_same_store(store),
147            Extern::Global(g) => g.comes_from_same_store(store),
148            Extern::Memory(m) => m.comes_from_same_store(store),
149            Extern::SharedMemory(m) => Engine::same(m.engine(), store.engine()),
150            Extern::Table(t) => t.comes_from_same_store(store),
151            Extern::Tag(t) => t.comes_from_same_store(store),
152        }
153    }
154}
155
156impl From<Func> for Extern {
157    fn from(r: Func) -> Self {
158        Extern::Func(r)
159    }
160}
161
162impl From<Global> for Extern {
163    fn from(r: Global) -> Self {
164        Extern::Global(r)
165    }
166}
167
168impl From<Memory> for Extern {
169    fn from(r: Memory) -> Self {
170        Extern::Memory(r)
171    }
172}
173
174impl From<SharedMemory> for Extern {
175    fn from(r: SharedMemory) -> Self {
176        Extern::SharedMemory(r)
177    }
178}
179
180impl From<Table> for Extern {
181    fn from(r: Table) -> Self {
182        Extern::Table(r)
183    }
184}
185
186impl From<Tag> for Extern {
187    fn from(t: Tag) -> Self {
188        Extern::Tag(t)
189    }
190}
191
192// Exports
193
194/// An exported WebAssembly value.
195///
196/// This type is primarily accessed from the
197/// [`Instance::exports`](crate::Instance::exports) accessor and describes what
198/// names and items are exported from a wasm instance.
199#[derive(Clone)]
200pub struct Export<'instance> {
201    /// The name of the export.
202    name: &'instance str,
203
204    /// The definition of the export.
205    definition: Extern,
206}
207
208impl<'instance> Export<'instance> {
209    /// Creates a new export which is exported with the given `name` and has the
210    /// given `definition`.
211    pub(crate) fn new(name: &'instance str, definition: Extern) -> Export<'instance> {
212        Export { name, definition }
213    }
214
215    /// Returns the name by which this export is known.
216    pub fn name(&self) -> &'instance str {
217        self.name
218    }
219
220    /// Return the `ExternType` of this export.
221    ///
222    /// # Panics
223    ///
224    /// Panics if `store` does not own this `Extern`.
225    pub fn ty(&self, store: impl AsContext) -> ExternType {
226        self.definition.ty(store)
227    }
228
229    /// Consume this `Export` and return the contained `Extern`.
230    pub fn into_extern(self) -> Extern {
231        self.definition
232    }
233
234    /// Consume this `Export` and return the contained `Func`, if it's a function,
235    /// or `None` otherwise.
236    pub fn into_func(self) -> Option<Func> {
237        self.definition.into_func()
238    }
239
240    /// Consume this `Export` and return the contained `Table`, if it's a table,
241    /// or `None` otherwise.
242    pub fn into_table(self) -> Option<Table> {
243        self.definition.into_table()
244    }
245
246    /// Consume this `Export` and return the contained `Memory`, if it's a memory,
247    /// or `None` otherwise.
248    pub fn into_memory(self) -> Option<Memory> {
249        self.definition.into_memory()
250    }
251
252    /// Consume this `Export` and return the contained `Global`, if it's a global,
253    /// or `None` otherwise.
254    pub fn into_global(self) -> Option<Global> {
255        self.definition.into_global()
256    }
257
258    /// Consume this `Export` and return the contained `Tag`, if it's a tag,
259    /// or `None` otherwise.
260    pub fn into_tag(self) -> Option<Tag> {
261        self.definition.into_tag()
262    }
263}