From e2f63d174f82aa3a35f4f52cd6ec21901533e94d Mon Sep 17 00:00:00 2001 From: Syrus Date: Mon, 4 May 2020 17:05:48 -0700 Subject: [PATCH] Improved Module api along with Exports --- lib/api/src/module.rs | 14 ++++++-- lib/runtime/src/instance.rs | 2 +- lib/runtime/src/lib.rs | 4 ++- lib/runtime/src/module.rs | 66 +++++++++++++++++++++++++++++++++--- lib/wasm-common/src/types.rs | 14 +++++--- 5 files changed, 87 insertions(+), 13 deletions(-) diff --git a/lib/api/src/module.rs b/lib/api/src/module.rs index 131ea2547..4941ef9b0 100644 --- a/lib/api/src/module.rs +++ b/lib/api/src/module.rs @@ -7,7 +7,7 @@ use std::sync::Arc; use thiserror::Error; use wasmer_compiler::{CompileError, WasmError}; use wasmer_jit::{CompiledModule, DeserializeError, Resolver, SerializeError}; -use wasmer_runtime::InstanceHandle; +use wasmer_runtime::{ExportsIterator, InstanceHandle, Module as ModuleInfo}; #[derive(Error, Debug)] pub enum IoCompileError { @@ -274,11 +274,21 @@ impl Module { /// export.ty(); /// } /// ``` - pub fn exports<'a>(&'a self) -> impl Iterator + 'a { + pub fn exports<'a>(&'a self) -> ExportsIterator + 'a> { self.compiled.module().exports() } pub fn store(&self) -> &Store { &self.store } + + // The ABI of the ModuleInfo is very unstable, we refactor it very often. + // This funciton is public because in some cases it can be useful to get some + // extra information from the module. + // + // However, the usage is highly discouraged. + #[doc(hidden)] + pub fn info(&self) -> &ModuleInfo { + &self.compiled.module() + } } diff --git a/lib/runtime/src/instance.rs b/lib/runtime/src/instance.rs index e6352d2fd..4aa847d7d 100644 --- a/lib/runtime/src/instance.rs +++ b/lib/runtime/src/instance.rs @@ -339,7 +339,7 @@ impl Instance { /// Return an iterator over the exports of this instance. /// - /// Specifically, it provides access to the key-value pairs, where they keys + /// Specifically, it provides access to the key-value pairs, where the keys /// are export names, and the values are export declarations which can be /// resolved `lookup_by_declaration`. pub fn exports(&self) -> indexmap::map::Iter { diff --git a/lib/runtime/src/lib.rs b/lib/runtime/src/lib.rs index 0ef1b0aee..e9e649721 100644 --- a/lib/runtime/src/lib.rs +++ b/lib/runtime/src/lib.rs @@ -41,7 +41,9 @@ pub use crate::imports::Imports; pub use crate::instance::InstanceHandle; pub use crate::memory::LinearMemory; pub use crate::mmap::Mmap; -pub use crate::module::{MemoryPlan, MemoryStyle, Module, TableElements, TablePlan, TableStyle}; +pub use crate::module::{ + ExportsIterator, MemoryPlan, MemoryStyle, Module, TableElements, TablePlan, TableStyle, +}; pub use crate::probestack::PROBESTACK; pub use crate::sig_registry::SignatureRegistry; pub use crate::table::Table; diff --git a/lib/runtime/src/module.rs b/lib/runtime/src/module.rs index 2122d44e2..fff482bd3 100644 --- a/lib/runtime/src/module.rs +++ b/lib/runtime/src/module.rs @@ -5,6 +5,7 @@ use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::fmt; +use std::iter::ExactSizeIterator; use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; use std::sync::Arc; use wasm_common::entity::{EntityRef, PrimaryMap}; @@ -134,7 +135,7 @@ pub struct Module { /// WebAssembly function signatures. pub signatures: PrimaryMap, - /// Types of functions (imported and local). + /// WebAssembly functions (imported and local). pub functions: PrimaryMap, /// WebAssembly tables (imported and local). @@ -206,8 +207,8 @@ impl Module { } /// Get the export types of the module - pub fn exports<'a>(&'a self) -> impl Iterator + 'a { - self.exports.iter().map(move |(name, export_index)| { + pub fn exports<'a>(&'a self) -> ExportsIterator + 'a> { + let iter = self.exports.iter().map(move |(name, export_index)| { let extern_type = match export_index { ExportIndex::Function(i) => { let signature = self.functions.get(i.clone()).unwrap(); @@ -228,7 +229,11 @@ impl Module { } }; ExportType::new(name, extern_type) - }) + }); + ExportsIterator { + iter, + size: self.exports.len(), + } } /// Get the export types of the module @@ -348,3 +353,56 @@ impl fmt::Display for Module { write!(f, "{}", self.name()) } } + +// Code inspired from +// https://www.reddit.com/r/rust/comments/9vspv4/extending_iterators_ergonomically/ +/// This iterator allows us to iterate +pub struct ExportsIterator + Sized> { + iter: I, + size: usize, +} + +impl + Sized> ExactSizeIterator for ExportsIterator { + // We can easily calculate the remaining number of iterations. + fn len(&self) -> usize { + self.size + } +} + +impl + Sized> ExportsIterator { + /// Get only the functions + pub fn functions(self) -> impl Iterator> + Sized { + self.iter.filter_map(|extern_| match extern_.ty() { + ExternType::Function(ty) => Some(ExportType::new(extern_.name(), ty.clone())), + _ => None, + }) + } + /// Get only the memories + pub fn memories(self) -> impl Iterator> + Sized { + self.iter.filter_map(|extern_| match extern_.ty() { + ExternType::Memory(ty) => Some(ExportType::new(extern_.name(), ty.clone())), + _ => None, + }) + } + /// Get only the tables + pub fn tables(self) -> impl Iterator> + Sized { + self.iter.filter_map(|extern_| match extern_.ty() { + ExternType::Table(ty) => Some(ExportType::new(extern_.name(), ty.clone())), + _ => None, + }) + } + /// Get only the globals + pub fn globals(self) -> impl Iterator> + Sized { + self.iter.filter_map(|extern_| match extern_.ty() { + ExternType::Global(ty) => Some(ExportType::new(extern_.name(), ty.clone())), + _ => None, + }) + } +} + +impl + Sized> Iterator for ExportsIterator { + type Item = ExportType; + fn next(&mut self) -> Option { + self.iter.next() + } +} diff --git a/lib/wasm-common/src/types.rs b/lib/wasm-common/src/types.rs index 5e608133b..a11435379 100644 --- a/lib/wasm-common/src/types.rs +++ b/lib/wasm-common/src/types.rs @@ -502,17 +502,21 @@ impl ImportType { /// [`Module::exports`](crate::Module::exports) accessor and describes what /// names are exported from a wasm module and the type of the item that is /// exported. +/// +/// The `` refefers to `ExternType`, however it can also refer to use +/// `MemoryType`, `TableType`, `FunctionType` and `GlobalType` for ease of +/// use. #[derive(Debug, Clone)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -pub struct ExportType { +pub struct ExportType { name: String, - ty: ExternType, + ty: T, } -impl ExportType { +impl ExportType { /// Creates a new export which is exported with the given `name` and has the /// given `ty`. - pub fn new(name: &str, ty: ExternType) -> ExportType { + pub fn new(name: &str, ty: T) -> Self { ExportType { name: name.to_string(), ty, @@ -525,7 +529,7 @@ impl ExportType { } /// Returns the type of this export. - pub fn ty(&self) -> &ExternType { + pub fn ty(&self) -> &T { &self.ty } }