1 use crate::store::StoreOpaque;
2 use crate::{AsContext, Engine, ExternType, Func, Memory, SharedMemory};
3 
4 mod global;
5 mod table;
6 mod tag;
7 
8 pub use global::Global;
9 pub use table::Table;
10 pub 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)]
22 pub 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 
40 impl Extern {
41     /// Returns the underlying `Func`, if this external is a function.
42     ///
43     /// Returns `None` if this is not a function.
44     #[inline]
into_func(self) -> Option<Func>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]
into_global(self) -> Option<Global>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]
into_table(self) -> Option<Table>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]
into_memory(self) -> Option<Memory>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]
into_shared_memory(self) -> Option<SharedMemory>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]
into_tag(self) -> Option<Tag>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.
ty(&self, store: impl AsContext) -> ExternType116     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 
from_wasmtime_export( wasmtime_export: crate::runtime::vm::Export, engine: &Engine, ) -> Extern128     pub(crate) fn from_wasmtime_export(
129         wasmtime_export: crate::runtime::vm::Export,
130         engine: &Engine,
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, 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 
comes_from_same_store(&self, store: &StoreOpaque) -> bool144     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 
156 impl From<Func> for Extern {
from(r: Func) -> Self157     fn from(r: Func) -> Self {
158         Extern::Func(r)
159     }
160 }
161 
162 impl From<Global> for Extern {
from(r: Global) -> Self163     fn from(r: Global) -> Self {
164         Extern::Global(r)
165     }
166 }
167 
168 impl From<Memory> for Extern {
from(r: Memory) -> Self169     fn from(r: Memory) -> Self {
170         Extern::Memory(r)
171     }
172 }
173 
174 impl From<SharedMemory> for Extern {
from(r: SharedMemory) -> Self175     fn from(r: SharedMemory) -> Self {
176         Extern::SharedMemory(r)
177     }
178 }
179 
180 impl From<Table> for Extern {
from(r: Table) -> Self181     fn from(r: Table) -> Self {
182         Extern::Table(r)
183     }
184 }
185 
186 impl From<Tag> for Extern {
from(t: Tag) -> Self187     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)]
200 pub 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 
208 impl<'instance> Export<'instance> {
209     /// Creates a new export which is exported with the given `name` and has the
210     /// given `definition`.
new(name: &'instance str, definition: Extern) -> Export<'instance>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.
name(&self) -> &'instance str216     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`.
ty(&self, store: impl AsContext) -> ExternType225     pub fn ty(&self, store: impl AsContext) -> ExternType {
226         self.definition.ty(store)
227     }
228 
229     /// Consume this `Export` and return the contained `Extern`.
into_extern(self) -> Extern230     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.
into_func(self) -> Option<Func>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.
into_table(self) -> Option<Table>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.
into_memory(self) -> Option<Memory>248     pub fn into_memory(self) -> Option<Memory> {
249         self.definition.into_memory()
250     }
251 
252     /// Consume this `Export` and return the contained `SharedMemory`, if it's
253     /// a shared memory, or `None` otherwise.
into_shared_memory(self) -> Option<SharedMemory>254     pub fn into_shared_memory(self) -> Option<SharedMemory> {
255         self.definition.into_shared_memory()
256     }
257 
258     /// Consume this `Export` and return the contained `Global`, if it's a global,
259     /// or `None` otherwise.
into_global(self) -> Option<Global>260     pub fn into_global(self) -> Option<Global> {
261         self.definition.into_global()
262     }
263 
264     /// Consume this `Export` and return the contained `Tag`, if it's a tag,
265     /// or `None` otherwise.
into_tag(self) -> Option<Tag>266     pub fn into_tag(self) -> Option<Tag> {
267         self.definition.into_tag()
268     }
269 }
270