1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
use super::GlobalIdx;
use crate::{errors::ModuleError, ExternType, Module};
use alloc::{boxed::Box, collections::btree_map::Iter as BTreeIter};
/// The index of a function declaration within a [`Module`].
///
/// [`Module`]: [`super::Module`]
#[derive(Debug, Copy, Clone)]
pub struct FuncIdx(u32);
impl From<u32> for FuncIdx {
fn from(index: u32) -> Self {
Self(index)
}
}
impl FuncIdx {
/// Returns the [`FuncIdx`] as `u32`.
pub fn into_u32(self) -> u32 {
self.0
}
}
/// The index of a table declaration within a [`Module`].
///
/// [`Module`]: [`super::Module`]
#[derive(Debug, Copy, Clone)]
pub struct TableIdx(u32);
impl From<u32> for TableIdx {
fn from(index: u32) -> Self {
Self(index)
}
}
impl TableIdx {
/// Returns the [`TableIdx`] as `u32`.
pub fn into_u32(self) -> u32 {
self.0
}
}
/// The index of a linear memory declaration within a [`Module`].
///
/// [`Module`]: [`super::Module`]
#[derive(Debug, Copy, Clone)]
pub struct MemoryIdx(u32);
impl From<u32> for MemoryIdx {
fn from(index: u32) -> Self {
Self(index)
}
}
impl MemoryIdx {
/// Returns the [`MemoryIdx`] as `u32`.
pub fn into_u32(self) -> u32 {
self.0
}
}
/// An external item of an [`ExportType`] definition within a [`Module`].
///
/// [`Module`]: [`crate::Module`]
#[derive(Debug, Copy, Clone)]
pub enum ExternIdx {
/// An exported function and its index within the [`Module`].
///
/// [`Module`]: [`super::Module`]
Func(FuncIdx),
/// An exported table and its index within the [`Module`].
///
/// [`Module`]: [`super::Module`]
Table(TableIdx),
/// An exported linear memory and its index within the [`Module`].
///
/// [`Module`]: [`super::Module`]
Memory(MemoryIdx),
/// An exported global variable and its index within the [`Module`].
///
/// [`Module`]: [`super::Module`]
Global(GlobalIdx),
}
impl ExternIdx {
/// Create a new [`ExternIdx`] from the given [`wasmparser::ExternalKind`] and `index`.
///
/// # Errors
///
/// If an unsupported external definition is encountered.
pub fn new(kind: wasmparser::ExternalKind, index: u32) -> Result<Self, ModuleError> {
match kind {
wasmparser::ExternalKind::Func => Ok(ExternIdx::Func(FuncIdx(index))),
wasmparser::ExternalKind::Table => Ok(ExternIdx::Table(TableIdx(index))),
wasmparser::ExternalKind::Memory => Ok(ExternIdx::Memory(MemoryIdx(index))),
wasmparser::ExternalKind::Global => Ok(ExternIdx::Global(GlobalIdx::from(index))),
wasmparser::ExternalKind::Tag => {
panic!("wasmi does not support the `exception-handling` Wasm proposal")
}
}
}
}
/// An iterator over the exports of a [`Module`].
///
/// [`Module`]: [`super::Module`]
#[derive(Debug)]
pub struct ModuleExportsIter<'module> {
exports: BTreeIter<'module, Box<str>, ExternIdx>,
module: &'module Module,
}
/// A descriptor for an exported WebAssembly value of a [`Module`].
///
/// This type is primarily accessed from the [`Module::exports`] method and describes
/// what names are exported from a Wasm [`Module`] and the type of the item that is exported.
#[derive(Debug)]
pub struct ExportType<'module> {
name: &'module str,
ty: ExternType,
}
impl<'module> ExportType<'module> {
/// Returns the name by which the export is known.
pub fn name(&self) -> &'module str {
self.name
}
/// Returns the type of the exported item.
pub fn ty(&self) -> &ExternType {
&self.ty
}
}
impl<'module> ModuleExportsIter<'module> {
/// Creates a new [`ModuleExportsIter`] from the given [`Module`].
pub(super) fn new(module: &'module Module) -> Self {
Self {
exports: module.exports.iter(),
module,
}
}
}
impl<'module> Iterator for ModuleExportsIter<'module> {
type Item = ExportType<'module>;
fn next(&mut self) -> Option<Self::Item> {
self.exports.next().map(|(name, idx)| {
let ty = self.module.get_extern_type(*idx);
ExportType { name, ty }
})
}
}