wasmtime/runtime/
externals.rs

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