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) unsafe 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 { memory, shared } => {
135                if shared {
136                    Extern::SharedMemory(SharedMemory::from_memory(memory, store))
137                } else {
138                    Extern::Memory(memory)
139                }
140            }
141            crate::runtime::vm::Export::Global(g) => Extern::Global(g),
142            crate::runtime::vm::Export::Table(t) => Extern::Table(t),
143            crate::runtime::vm::Export::Tag(t) => Extern::Tag(t),
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) => g.comes_from_same_store(store),
151            Extern::Memory(m) => m.comes_from_same_store(store),
152            Extern::SharedMemory(m) => Engine::same(m.engine(), store.engine()),
153            Extern::Table(t) => t.comes_from_same_store(store),
154            Extern::Tag(t) => t.comes_from_same_store(store),
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}