wasmtime/externals.rs
1use crate::store::{StoreData, StoreOpaque, Stored};
2use crate::trampoline::{generate_global_export, generate_table_export};
3use crate::{
4 AsContext, AsContextMut, Engine, ExternRef, ExternType, Func, GlobalType, Memory, Mutability,
5 SharedMemory, TableType, Val, ValType,
6};
7use anyhow::{anyhow, bail, Result};
8use std::mem;
9use std::ptr;
10use wasmtime_runtime::{self as runtime, InstanceHandle};
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}
36
37impl Extern {
38 /// Returns the underlying `Func`, if this external is a function.
39 ///
40 /// Returns `None` if this is not a function.
41 pub fn into_func(self) -> Option<Func> {
42 match self {
43 Extern::Func(func) => Some(func),
44 _ => None,
45 }
46 }
47
48 /// Returns the underlying `Global`, if this external is a global.
49 ///
50 /// Returns `None` if this is not a global.
51 pub fn into_global(self) -> Option<Global> {
52 match self {
53 Extern::Global(global) => Some(global),
54 _ => None,
55 }
56 }
57
58 /// Returns the underlying `Table`, if this external is a table.
59 ///
60 /// Returns `None` if this is not a table.
61 pub fn into_table(self) -> Option<Table> {
62 match self {
63 Extern::Table(table) => Some(table),
64 _ => None,
65 }
66 }
67
68 /// Returns the underlying `Memory`, if this external is a memory.
69 ///
70 /// Returns `None` if this is not a memory.
71 pub fn into_memory(self) -> Option<Memory> {
72 match self {
73 Extern::Memory(memory) => Some(memory),
74 _ => None,
75 }
76 }
77
78 /// Returns the underlying `SharedMemory`, if this external is a shared
79 /// memory.
80 ///
81 /// Returns `None` if this is not a shared memory.
82 pub fn into_shared_memory(self) -> Option<SharedMemory> {
83 match self {
84 Extern::SharedMemory(memory) => Some(memory),
85 _ => None,
86 }
87 }
88
89 /// Returns the type associated with this `Extern`.
90 ///
91 /// The `store` argument provided must own this `Extern` and is used to look
92 /// up type information.
93 ///
94 /// # Panics
95 ///
96 /// Panics if this item does not belong to the `store` provided.
97 pub fn ty(&self, store: impl AsContext) -> ExternType {
98 let store = store.as_context();
99 match self {
100 Extern::Func(ft) => ExternType::Func(ft.ty(store)),
101 Extern::Memory(ft) => ExternType::Memory(ft.ty(store)),
102 Extern::SharedMemory(ft) => ExternType::Memory(ft.ty()),
103 Extern::Table(tt) => ExternType::Table(tt.ty(store)),
104 Extern::Global(gt) => ExternType::Global(gt.ty(store)),
105 }
106 }
107
108 pub(crate) unsafe fn from_wasmtime_export(
109 wasmtime_export: wasmtime_runtime::Export,
110 store: &mut StoreOpaque,
111 ) -> Extern {
112 match wasmtime_export {
113 wasmtime_runtime::Export::Function(f) => {
114 Extern::Func(Func::from_wasmtime_function(f, store))
115 }
116 wasmtime_runtime::Export::Memory(m) => {
117 if m.memory.memory.shared {
118 Extern::SharedMemory(SharedMemory::from_wasmtime_memory(m, store))
119 } else {
120 Extern::Memory(Memory::from_wasmtime_memory(m, store))
121 }
122 }
123 wasmtime_runtime::Export::Global(g) => {
124 Extern::Global(Global::from_wasmtime_global(g, store))
125 }
126 wasmtime_runtime::Export::Table(t) => {
127 Extern::Table(Table::from_wasmtime_table(t, store))
128 }
129 }
130 }
131
132 pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool {
133 match self {
134 Extern::Func(f) => f.comes_from_same_store(store),
135 Extern::Global(g) => store.store_data().contains(g.0),
136 Extern::Memory(m) => m.comes_from_same_store(store),
137 Extern::SharedMemory(m) => Engine::same(m.engine(), store.engine()),
138 Extern::Table(t) => store.store_data().contains(t.0),
139 }
140 }
141}
142
143impl From<Func> for Extern {
144 fn from(r: Func) -> Self {
145 Extern::Func(r)
146 }
147}
148
149impl From<Global> for Extern {
150 fn from(r: Global) -> Self {
151 Extern::Global(r)
152 }
153}
154
155impl From<Memory> for Extern {
156 fn from(r: Memory) -> Self {
157 Extern::Memory(r)
158 }
159}
160
161impl From<SharedMemory> for Extern {
162 fn from(r: SharedMemory) -> Self {
163 Extern::SharedMemory(r)
164 }
165}
166
167impl From<Table> for Extern {
168 fn from(r: Table) -> Self {
169 Extern::Table(r)
170 }
171}
172
173/// A WebAssembly `global` value which can be read and written to.
174///
175/// A `global` in WebAssembly is sort of like a global variable within an
176/// [`Instance`](crate::Instance). The `global.get` and `global.set`
177/// instructions will modify and read global values in a wasm module. Globals
178/// can either be imported or exported from wasm modules.
179///
180/// A [`Global`] "belongs" to the store that it was originally created within
181/// (either via [`Global::new`] or via instantiating a
182/// [`Module`](crate::Module)). Operations on a [`Global`] only work with the
183/// store it belongs to, and if another store is passed in by accident then
184/// methods will panic.
185#[derive(Copy, Clone, Debug)]
186#[repr(transparent)] // here for the C API
187pub struct Global(Stored<wasmtime_runtime::ExportGlobal>);
188
189impl Global {
190 /// Creates a new WebAssembly `global` value with the provide type `ty` and
191 /// initial value `val`.
192 ///
193 /// The `store` argument will be the owner of the [`Global`] returned. Using
194 /// the returned [`Global`] other items in the store may access this global.
195 /// For example this could be provided as an argument to
196 /// [`Instance::new`](crate::Instance::new) or
197 /// [`Linker::define`](crate::Linker::define).
198 ///
199 /// # Errors
200 ///
201 /// Returns an error if the `ty` provided does not match the type of the
202 /// value `val`, or if `val` comes from a different store than `store`.
203 ///
204 /// # Examples
205 ///
206 /// ```
207 /// # use wasmtime::*;
208 /// # fn main() -> anyhow::Result<()> {
209 /// let engine = Engine::default();
210 /// let mut store = Store::new(&engine, ());
211 ///
212 /// let ty = GlobalType::new(ValType::I32, Mutability::Const);
213 /// let i32_const = Global::new(&mut store, ty, 1i32.into())?;
214 /// let ty = GlobalType::new(ValType::F64, Mutability::Var);
215 /// let f64_mut = Global::new(&mut store, ty, 2.0f64.into())?;
216 ///
217 /// let module = Module::new(
218 /// &engine,
219 /// "(module
220 /// (global (import \"\" \"i32-const\") i32)
221 /// (global (import \"\" \"f64-mut\") (mut f64))
222 /// )"
223 /// )?;
224 ///
225 /// let mut linker = Linker::new(&engine);
226 /// linker.define(&store, "", "i32-const", i32_const)?;
227 /// linker.define(&store, "", "f64-mut", f64_mut)?;
228 ///
229 /// let instance = linker.instantiate(&mut store, &module)?;
230 /// // ...
231 /// # Ok(())
232 /// # }
233 /// ```
234 pub fn new(mut store: impl AsContextMut, ty: GlobalType, val: Val) -> Result<Global> {
235 Global::_new(store.as_context_mut().0, ty, val)
236 }
237
238 fn _new(store: &mut StoreOpaque, ty: GlobalType, val: Val) -> Result<Global> {
239 if !val.comes_from_same_store(store) {
240 bail!("cross-`Store` globals are not supported");
241 }
242 if val.ty() != *ty.content() {
243 bail!("value provided does not match the type of this global");
244 }
245 unsafe {
246 let wasmtime_export = generate_global_export(store, &ty, val)?;
247 Ok(Global::from_wasmtime_global(wasmtime_export, store))
248 }
249 }
250
251 /// Returns the underlying type of this `global`.
252 ///
253 /// # Panics
254 ///
255 /// Panics if `store` does not own this global.
256 pub fn ty(&self, store: impl AsContext) -> GlobalType {
257 let store = store.as_context();
258 let ty = &store[self.0].global;
259 GlobalType::from_wasmtime_global(&ty)
260 }
261
262 /// Returns the current [`Val`] of this global.
263 ///
264 /// # Panics
265 ///
266 /// Panics if `store` does not own this global.
267 pub fn get(&self, mut store: impl AsContextMut) -> Val {
268 unsafe {
269 let store = store.as_context_mut();
270 let definition = &*store[self.0].definition;
271 match self.ty(&store).content() {
272 ValType::I32 => Val::from(*definition.as_i32()),
273 ValType::I64 => Val::from(*definition.as_i64()),
274 ValType::F32 => Val::F32(*definition.as_u32()),
275 ValType::F64 => Val::F64(*definition.as_u64()),
276 ValType::ExternRef => Val::ExternRef(
277 definition
278 .as_externref()
279 .clone()
280 .map(|inner| ExternRef { inner }),
281 ),
282 ValType::FuncRef => {
283 Val::FuncRef(Func::from_raw(store, definition.as_anyfunc() as usize))
284 }
285 ValType::V128 => Val::V128(*definition.as_u128()),
286 }
287 }
288 }
289
290 /// Attempts to set the current value of this global to [`Val`].
291 ///
292 /// # Errors
293 ///
294 /// Returns an error if this global has a different type than `Val`, if
295 /// it's not a mutable global, or if `val` comes from a different store than
296 /// the one provided.
297 ///
298 /// # Panics
299 ///
300 /// Panics if `store` does not own this global.
301 pub fn set(&self, mut store: impl AsContextMut, val: Val) -> Result<()> {
302 let store = store.as_context_mut().0;
303 let ty = self.ty(&store);
304 if ty.mutability() != Mutability::Var {
305 bail!("immutable global cannot be set");
306 }
307 let ty = ty.content();
308 if val.ty() != *ty {
309 bail!("global of type {:?} cannot be set to {:?}", ty, val.ty());
310 }
311 if !val.comes_from_same_store(store) {
312 bail!("cross-`Store` values are not supported");
313 }
314 unsafe {
315 let definition = &mut *store[self.0].definition;
316 match val {
317 Val::I32(i) => *definition.as_i32_mut() = i,
318 Val::I64(i) => *definition.as_i64_mut() = i,
319 Val::F32(f) => *definition.as_u32_mut() = f,
320 Val::F64(f) => *definition.as_u64_mut() = f,
321 Val::FuncRef(f) => {
322 *definition.as_anyfunc_mut() = f.map_or(ptr::null(), |f| {
323 f.caller_checked_anyfunc(store).as_ptr().cast()
324 });
325 }
326 Val::ExternRef(x) => {
327 let old = mem::replace(definition.as_externref_mut(), x.map(|x| x.inner));
328 drop(old);
329 }
330 Val::V128(i) => *definition.as_u128_mut() = i,
331 }
332 }
333 Ok(())
334 }
335
336 pub(crate) unsafe fn from_wasmtime_global(
337 wasmtime_export: wasmtime_runtime::ExportGlobal,
338 store: &mut StoreOpaque,
339 ) -> Global {
340 Global(store.store_data_mut().insert(wasmtime_export))
341 }
342
343 pub(crate) fn wasmtime_ty<'a>(&self, data: &'a StoreData) -> &'a wasmtime_environ::Global {
344 &data[self.0].global
345 }
346
347 pub(crate) fn vmimport(&self, store: &StoreOpaque) -> wasmtime_runtime::VMGlobalImport {
348 wasmtime_runtime::VMGlobalImport {
349 from: store[self.0].definition,
350 }
351 }
352}
353
354/// A WebAssembly `table`, or an array of values.
355///
356/// Like [`Memory`] a table is an indexed array of values, but unlike [`Memory`]
357/// it's an array of WebAssembly reference type values rather than bytes. One of
358/// the most common usages of a table is a function table for wasm modules (a
359/// `funcref` table), where each element has the `ValType::FuncRef` type.
360///
361/// A [`Table`] "belongs" to the store that it was originally created within
362/// (either via [`Table::new`] or via instantiating a
363/// [`Module`](crate::Module)). Operations on a [`Table`] only work with the
364/// store it belongs to, and if another store is passed in by accident then
365/// methods will panic.
366#[derive(Copy, Clone, Debug)]
367#[repr(transparent)] // here for the C API
368pub struct Table(Stored<wasmtime_runtime::ExportTable>);
369
370impl Table {
371 /// Creates a new [`Table`] with the given parameters.
372 ///
373 /// * `store` - the owner of the resulting [`Table`]
374 /// * `ty` - the type of this table, containing both the element type as
375 /// well as the initial size and maximum size, if any.
376 /// * `init` - the initial value to fill all table entries with, if the
377 /// table starts with an initial size.
378 ///
379 /// # Errors
380 ///
381 /// Returns an error if `init` does not match the element type of the table,
382 /// or if `init` does not belong to the `store` provided.
383 ///
384 /// # Panics
385 ///
386 /// This function will panic when used with a [`Store`](`crate::Store`)
387 /// which has a [`ResourceLimiterAsync`](`crate::ResourceLimiterAsync`)
388 /// (see also: [`Store::limiter_async`](`crate::Store::limiter_async`).
389 /// When using an async resource limiter, use [`Table::new_async`]
390 /// instead.
391 ///
392 /// # Examples
393 ///
394 /// ```
395 /// # use wasmtime::*;
396 /// # fn main() -> anyhow::Result<()> {
397 /// let engine = Engine::default();
398 /// let mut store = Store::new(&engine, ());
399 ///
400 /// let ty = TableType::new(ValType::FuncRef, 2, None);
401 /// let table = Table::new(&mut store, ty, Val::FuncRef(None))?;
402 ///
403 /// let module = Module::new(
404 /// &engine,
405 /// "(module
406 /// (table (import \"\" \"\") 2 funcref)
407 /// (func $f (result i32)
408 /// i32.const 10)
409 /// (elem (i32.const 0) $f)
410 /// )"
411 /// )?;
412 ///
413 /// let instance = Instance::new(&mut store, &module, &[table.into()])?;
414 /// // ...
415 /// # Ok(())
416 /// # }
417 /// ```
418 pub fn new(mut store: impl AsContextMut, ty: TableType, init: Val) -> Result<Table> {
419 Table::_new(store.as_context_mut().0, ty, init)
420 }
421
422 #[cfg_attr(nightlydoc, doc(cfg(feature = "async")))]
423 /// Async variant of [`Table::new`]. You must use this variant with
424 /// [`Store`](`crate::Store`)s which have a
425 /// [`ResourceLimiterAsync`](`crate::ResourceLimiterAsync`).
426 ///
427 /// # Panics
428 ///
429 /// This function will panic when used with a non-async
430 /// [`Store`](`crate::Store`)
431 #[cfg(feature = "async")]
432 pub async fn new_async<T>(
433 mut store: impl AsContextMut<Data = T>,
434 ty: TableType,
435 init: Val,
436 ) -> Result<Table>
437 where
438 T: Send,
439 {
440 let mut store = store.as_context_mut();
441 assert!(
442 store.0.async_support(),
443 "cannot use `new_async` without enabling async support on the config"
444 );
445 store
446 .on_fiber(|store| Table::_new(store.0, ty, init))
447 .await?
448 }
449
450 fn _new(store: &mut StoreOpaque, ty: TableType, init: Val) -> Result<Table> {
451 let wasmtime_export = generate_table_export(store, &ty)?;
452 let init = init.into_table_element(store, ty.element())?;
453 unsafe {
454 let table = Table::from_wasmtime_table(wasmtime_export, store);
455 (*table.wasmtime_table(store, std::iter::empty())).fill(0, init, ty.minimum())?;
456
457 Ok(table)
458 }
459 }
460
461 /// Returns the underlying type of this table, including its element type as
462 /// well as the maximum/minimum lower bounds.
463 ///
464 /// # Panics
465 ///
466 /// Panics if `store` does not own this table.
467 pub fn ty(&self, store: impl AsContext) -> TableType {
468 let store = store.as_context();
469 let ty = &store[self.0].table.table;
470 TableType::from_wasmtime_table(ty)
471 }
472
473 fn wasmtime_table(
474 &self,
475 store: &mut StoreOpaque,
476 lazy_init_range: impl Iterator<Item = u32>,
477 ) -> *mut runtime::Table {
478 unsafe {
479 let export = &store[self.0];
480 let mut handle = InstanceHandle::from_vmctx(export.vmctx);
481 let idx = handle.table_index(&*export.definition);
482 handle.get_defined_table_with_lazy_init(idx, lazy_init_range)
483 }
484 }
485
486 /// Returns the table element value at `index`.
487 ///
488 /// Returns `None` if `index` is out of bounds.
489 ///
490 /// # Panics
491 ///
492 /// Panics if `store` does not own this table.
493 pub fn get(&self, mut store: impl AsContextMut, index: u32) -> Option<Val> {
494 let store = store.as_context_mut().0;
495 let table = self.wasmtime_table(store, std::iter::once(index));
496 unsafe {
497 match (*table).get(index)? {
498 runtime::TableElement::FuncRef(f) => {
499 let func = Func::from_caller_checked_anyfunc(store, f);
500 Some(Val::FuncRef(func))
501 }
502 runtime::TableElement::ExternRef(None) => Some(Val::ExternRef(None)),
503 runtime::TableElement::ExternRef(Some(x)) => {
504 Some(Val::ExternRef(Some(ExternRef { inner: x })))
505 }
506 runtime::TableElement::UninitFunc => {
507 unreachable!("lazy init above should have converted UninitFunc")
508 }
509 }
510 }
511 }
512
513 /// Writes the `val` provided into `index` within this table.
514 ///
515 /// # Errors
516 ///
517 /// Returns an error if `index` is out of bounds, if `val` does not have
518 /// the right type to be stored in this table, or if `val` belongs to a
519 /// different store.
520 ///
521 /// # Panics
522 ///
523 /// Panics if `store` does not own this table.
524 pub fn set(&self, mut store: impl AsContextMut, index: u32, val: Val) -> Result<()> {
525 let store = store.as_context_mut().0;
526 let ty = self.ty(&store).element().clone();
527 let val = val.into_table_element(store, ty)?;
528 let table = self.wasmtime_table(store, std::iter::empty());
529 unsafe {
530 (*table)
531 .set(index, val)
532 .map_err(|()| anyhow!("table element index out of bounds"))
533 }
534 }
535
536 /// Returns the current size of this table.
537 ///
538 /// # Panics
539 ///
540 /// Panics if `store` does not own this table.
541 pub fn size(&self, store: impl AsContext) -> u32 {
542 self.internal_size(store.as_context().0)
543 }
544
545 pub(crate) fn internal_size(&self, store: &StoreOpaque) -> u32 {
546 unsafe { (*store[self.0].definition).current_elements }
547 }
548
549 /// Grows the size of this table by `delta` more elements, initialization
550 /// all new elements to `init`.
551 ///
552 /// Returns the previous size of this table if successful.
553 ///
554 /// # Errors
555 ///
556 /// Returns an error if the table cannot be grown by `delta`, for example
557 /// if it would cause the table to exceed its maximum size. Also returns an
558 /// error if `init` is not of the right type or if `init` does not belong to
559 /// `store`.
560 ///
561 /// # Panics
562 ///
563 /// Panics if `store` does not own this table.
564 ///
565 /// This function will panic when used with a [`Store`](`crate::Store`)
566 /// which has a [`ResourceLimiterAsync`](`crate::ResourceLimiterAsync`)
567 /// (see also: [`Store::limiter_async`](`crate::Store::limiter_async`)).
568 /// When using an async resource limiter, use [`Table::grow_async`]
569 /// instead.
570 pub fn grow(&self, mut store: impl AsContextMut, delta: u32, init: Val) -> Result<u32> {
571 let store = store.as_context_mut().0;
572 let ty = self.ty(&store).element().clone();
573 let init = init.into_table_element(store, ty)?;
574 let table = self.wasmtime_table(store, std::iter::empty());
575 unsafe {
576 match (*table).grow(delta, init, store)? {
577 Some(size) => {
578 let vm = (*table).vmtable();
579 *store[self.0].definition = vm;
580 Ok(size)
581 }
582 None => bail!("failed to grow table by `{}`", delta),
583 }
584 }
585 }
586
587 #[cfg_attr(nightlydoc, doc(cfg(feature = "async")))]
588 /// Async variant of [`Table::grow`]. Required when using a
589 /// [`ResourceLimiterAsync`](`crate::ResourceLimiterAsync`).
590 ///
591 /// # Panics
592 ///
593 /// This function will panic when used with a non-async
594 /// [`Store`](`crate::Store`).
595 #[cfg(feature = "async")]
596 pub async fn grow_async<T>(
597 &self,
598 mut store: impl AsContextMut<Data = T>,
599 delta: u32,
600 init: Val,
601 ) -> Result<u32>
602 where
603 T: Send,
604 {
605 let mut store = store.as_context_mut();
606 assert!(
607 store.0.async_support(),
608 "cannot use `grow_async` without enabling async support on the config"
609 );
610 store
611 .on_fiber(|store| self.grow(store, delta, init))
612 .await?
613 }
614
615 /// Copy `len` elements from `src_table[src_index..]` into
616 /// `dst_table[dst_index..]`.
617 ///
618 /// # Errors
619 ///
620 /// Returns an error if the range is out of bounds of either the source or
621 /// destination tables.
622 ///
623 /// # Panics
624 ///
625 /// Panics if `store` does not own either `dst_table` or `src_table`.
626 pub fn copy(
627 mut store: impl AsContextMut,
628 dst_table: &Table,
629 dst_index: u32,
630 src_table: &Table,
631 src_index: u32,
632 len: u32,
633 ) -> Result<()> {
634 let store = store.as_context_mut().0;
635 if dst_table.ty(&store).element() != src_table.ty(&store).element() {
636 bail!("tables do not have the same element type");
637 }
638
639 let dst_table = dst_table.wasmtime_table(store, std::iter::empty());
640 let src_range = src_index..(src_index.checked_add(len).unwrap_or(u32::MAX));
641 let src_table = src_table.wasmtime_table(store, src_range);
642 unsafe {
643 runtime::Table::copy(dst_table, src_table, dst_index, src_index, len)?;
644 }
645 Ok(())
646 }
647
648 /// Fill `table[dst..(dst + len)]` with the given value.
649 ///
650 /// # Errors
651 ///
652 /// Returns an error if
653 ///
654 /// * `val` is not of the same type as this table's
655 /// element type,
656 ///
657 /// * the region to be filled is out of bounds, or
658 ///
659 /// * `val` comes from a different `Store` from this table.
660 ///
661 /// # Panics
662 ///
663 /// Panics if `store` does not own either `dst_table` or `src_table`.
664 pub fn fill(&self, mut store: impl AsContextMut, dst: u32, val: Val, len: u32) -> Result<()> {
665 let store = store.as_context_mut().0;
666 let ty = self.ty(&store).element().clone();
667 let val = val.into_table_element(store, ty)?;
668
669 let table = self.wasmtime_table(store, std::iter::empty());
670 unsafe {
671 (*table).fill(dst, val, len)?;
672 }
673
674 Ok(())
675 }
676
677 pub(crate) unsafe fn from_wasmtime_table(
678 wasmtime_export: wasmtime_runtime::ExportTable,
679 store: &mut StoreOpaque,
680 ) -> Table {
681 Table(store.store_data_mut().insert(wasmtime_export))
682 }
683
684 pub(crate) fn wasmtime_ty<'a>(&self, data: &'a StoreData) -> &'a wasmtime_environ::Table {
685 &data[self.0].table.table
686 }
687
688 pub(crate) fn vmimport(&self, store: &StoreOpaque) -> wasmtime_runtime::VMTableImport {
689 let export = &store[self.0];
690 wasmtime_runtime::VMTableImport {
691 from: export.definition,
692 vmctx: export.vmctx,
693 }
694 }
695}
696
697// Exports
698
699/// An exported WebAssembly value.
700///
701/// This type is primarily accessed from the
702/// [`Instance::exports`](crate::Instance::exports) accessor and describes what
703/// names and items are exported from a wasm instance.
704#[derive(Clone)]
705pub struct Export<'instance> {
706 /// The name of the export.
707 name: &'instance str,
708
709 /// The definition of the export.
710 definition: Extern,
711}
712
713impl<'instance> Export<'instance> {
714 /// Creates a new export which is exported with the given `name` and has the
715 /// given `definition`.
716 pub(crate) fn new(name: &'instance str, definition: Extern) -> Export<'instance> {
717 Export { name, definition }
718 }
719
720 /// Returns the name by which this export is known.
721 pub fn name(&self) -> &'instance str {
722 self.name
723 }
724
725 /// Return the `ExternType` of this export.
726 ///
727 /// # Panics
728 ///
729 /// Panics if `store` does not own this `Extern`.
730 pub fn ty(&self, store: impl AsContext) -> ExternType {
731 self.definition.ty(store)
732 }
733
734 /// Consume this `Export` and return the contained `Extern`.
735 pub fn into_extern(self) -> Extern {
736 self.definition
737 }
738
739 /// Consume this `Export` and return the contained `Func`, if it's a function,
740 /// or `None` otherwise.
741 pub fn into_func(self) -> Option<Func> {
742 self.definition.into_func()
743 }
744
745 /// Consume this `Export` and return the contained `Table`, if it's a table,
746 /// or `None` otherwise.
747 pub fn into_table(self) -> Option<Table> {
748 self.definition.into_table()
749 }
750
751 /// Consume this `Export` and return the contained `Memory`, if it's a memory,
752 /// or `None` otherwise.
753 pub fn into_memory(self) -> Option<Memory> {
754 self.definition.into_memory()
755 }
756
757 /// Consume this `Export` and return the contained `Global`, if it's a global,
758 /// or `None` otherwise.
759 pub fn into_global(self) -> Option<Global> {
760 self.definition.into_global()
761 }
762}