use crate::{
AsContext,
Func,
FuncType,
Global,
GlobalType,
Memory,
MemoryType,
Table,
TableType,
collections::map::Iter as MapIter,
};
use alloc::boxed::Box;
use core::iter::FusedIterator;
/// An external item to a WebAssembly module.
///
/// This is returned from [`Instance::exports`](crate::Instance::exports)
/// or [`Instance::get_export`](crate::Instance::get_export).
#[derive(Debug, Copy, Clone)]
pub enum Extern {
/// A WebAssembly global which acts like a [`Cell<T>`] of sorts, supporting `get` and `set` operations.
///
/// [`Cell<T>`]: https://doc.rust-lang.org/core/cell/struct.Cell.html
Global(Global),
/// A WebAssembly table which is an array of function references.
Table(Table),
/// A WebAssembly linear memory.
Memory(Memory),
/// A WebAssembly function which can be called.
Func(Func),
}
impl From<Global> for Extern {
fn from(global: Global) -> Self {
Self::Global(global)
}
}
impl From<Table> for Extern {
fn from(table: Table) -> Self {
Self::Table(table)
}
}
impl From<Memory> for Extern {
fn from(memory: Memory) -> Self {
Self::Memory(memory)
}
}
impl From<Func> for Extern {
fn from(func: Func) -> Self {
Self::Func(func)
}
}
impl Extern {
/// Returns the underlying global variable if `self` is a global variable.
///
/// Returns `None` otherwise.
pub fn into_global(self) -> Option<Global> {
if let Self::Global(global) = self {
return Some(global);
}
None
}
/// Returns the underlying table if `self` is a table.
///
/// Returns `None` otherwise.
pub fn into_table(self) -> Option<Table> {
if let Self::Table(table) = self {
return Some(table);
}
None
}
/// Returns the underlying linear memory if `self` is a linear memory.
///
/// Returns `None` otherwise.
pub fn into_memory(self) -> Option<Memory> {
if let Self::Memory(memory) = self {
return Some(memory);
}
None
}
/// Returns the underlying function if `self` is a function.
///
/// Returns `None` otherwise.
pub fn into_func(self) -> Option<Func> {
if let Self::Func(func) = self {
return Some(func);
}
None
}
/// Returns the type associated with this [`Extern`].
///
/// # Panics
///
/// If this item does not belong to the `store` provided.
pub fn ty(&self, ctx: impl AsContext) -> ExternType {
match self {
Extern::Global(global) => global.ty(ctx).into(),
Extern::Table(table) => table.ty(ctx).into(),
Extern::Memory(memory) => memory.ty(ctx).into(),
Extern::Func(func) => func.ty(ctx).into(),
}
}
}
/// The type of an [`Extern`] item.
///
/// A list of all possible types which can be externally referenced from a WebAssembly module.
#[derive(Debug, Clone)]
pub enum ExternType {
/// The type of an [`Extern::Global`].
Global(GlobalType),
/// The type of an [`Extern::Table`].
Table(TableType),
/// The type of an [`Extern::Memory`].
Memory(MemoryType),
/// The type of an [`Extern::Func`].
Func(FuncType),
}
impl From<GlobalType> for ExternType {
fn from(global: GlobalType) -> Self {
Self::Global(global)
}
}
impl From<TableType> for ExternType {
fn from(table: TableType) -> Self {
Self::Table(table)
}
}
impl From<MemoryType> for ExternType {
fn from(memory: MemoryType) -> Self {
Self::Memory(memory)
}
}
impl From<FuncType> for ExternType {
fn from(func: FuncType) -> Self {
Self::Func(func)
}
}
impl ExternType {
/// Returns the underlying [`GlobalType`] or `None` if it is of a different type.
pub fn global(&self) -> Option<&GlobalType> {
match self {
Self::Global(ty) => Some(ty),
_ => None,
}
}
/// Returns the underlying [`TableType`] or `None` if it is of a different type.
pub fn table(&self) -> Option<&TableType> {
match self {
Self::Table(ty) => Some(ty),
_ => None,
}
}
/// Returns the underlying [`MemoryType`] or `None` if it is of a different type.
pub fn memory(&self) -> Option<&MemoryType> {
match self {
Self::Memory(ty) => Some(ty),
_ => None,
}
}
/// Returns the underlying [`FuncType`] or `None` if it is of a different type.
pub fn func(&self) -> Option<&FuncType> {
match self {
Self::Func(ty) => Some(ty),
_ => None,
}
}
}
/// An exported WebAssembly value.
///
/// This type is primarily accessed from the [`Instance::exports`](crate::Instance::exports) method
/// and describes what names and items are exported from a Wasm [`Instance`](crate::Instance).
#[derive(Debug, Clone)]
pub struct Export<'instance> {
/// The name of the exported item.
name: &'instance str,
/// The definition of the exported item.
definition: Extern,
}
impl<'instance> Export<'instance> {
/// Creates a new [`Export`] with the given `name` and `definition`.
pub(crate) fn new(name: &'instance str, definition: Extern) -> Export<'instance> {
Self { name, definition }
}
/// Returns the name by which this export is known.
pub fn name(&self) -> &'instance str {
self.name
}
/// Return the [`ExternType`] of this export.
///
/// # Panics
///
/// If `ctx` does not own this [`Export`].
pub fn ty(&self, ctx: impl AsContext) -> ExternType {
self.definition.ty(ctx)
}
/// Consume this [`Export`] and return the underlying [`Extern`].
pub fn into_extern(self) -> Extern {
self.definition
}
/// Returns the underlying [`Func`], if the [`Export`] is a function or `None` otherwise.
pub fn into_func(self) -> Option<Func> {
self.definition.into_func()
}
/// Returns the underlying [`Table`], if the [`Export`] is a table or `None` otherwise.
pub fn into_table(self) -> Option<Table> {
self.definition.into_table()
}
/// Returns the underlying [`Memory`], if the [`Export`] is a linear memory or `None` otherwise.
pub fn into_memory(self) -> Option<Memory> {
self.definition.into_memory()
}
/// Returns the underlying [`Global`], if the [`Export`] is a global variable or `None` otherwise.
pub fn into_global(self) -> Option<Global> {
self.definition.into_global()
}
}
/// An iterator over the [`Extern`] declarations of an [`Instance`](crate::Instance).
#[derive(Debug)]
pub struct ExportsIter<'instance> {
iter: MapIter<'instance, Box<str>, Extern>,
}
impl<'instance> ExportsIter<'instance> {
/// Creates a new [`ExportsIter`].
pub(super) fn new(iter: MapIter<'instance, Box<str>, Extern>) -> Self {
Self { iter }
}
/// Prepares an item to match the expected iterator `Item` signature.
#[allow(clippy::borrowed_box)]
fn convert_item((name, export): (&'instance Box<str>, &'instance Extern)) -> Export<'instance> {
Export::new(name, *export)
}
}
impl<'instance> Iterator for ExportsIter<'instance> {
type Item = Export<'instance>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(Self::convert_item)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl ExactSizeIterator for ExportsIter<'_> {}
impl FusedIterator for ExportsIter<'_> {}
use crate::;
use Box;
use FusedIterator;
/// An external item to a WebAssembly module.
///
/// This is returned from [`Instance::exports`](crate::Instance::exports)
/// or [`Instance::get_export`](crate::Instance::get_export).
/// The type of an [`Extern`] item.
///
/// A list of all possible types which can be externally referenced from a WebAssembly module.
/// An exported WebAssembly value.
///
/// This type is primarily accessed from the [`Instance::exports`](crate::Instance::exports) method
/// and describes what names and items are exported from a Wasm [`Instance`](crate::Instance).
/// An iterator over the [`Extern`] declarations of an [`Instance`](crate::Instance).