Improved Module api along with Exports

This commit is contained in:
Syrus
2020-05-04 17:05:48 -07:00
parent dad68819ff
commit e2f63d174f
5 changed files with 87 additions and 13 deletions

View File

@@ -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<Item = ExportType> + 'a {
pub fn exports<'a>(&'a self) -> ExportsIterator<impl Iterator<Item = ExportType> + '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()
}
}

View File

@@ -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<String, ExportIndex> {

View File

@@ -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;

View File

@@ -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<SignatureIndex, FunctionType>,
/// Types of functions (imported and local).
/// WebAssembly functions (imported and local).
pub functions: PrimaryMap<FunctionIndex, SignatureIndex>,
/// 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<Item = ExportType> + 'a {
self.exports.iter().map(move |(name, export_index)| {
pub fn exports<'a>(&'a self) -> ExportsIterator<impl Iterator<Item = ExportType> + '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<I: Iterator<Item = ExportType> + Sized> {
iter: I,
size: usize,
}
impl<I: Iterator<Item = ExportType> + Sized> ExactSizeIterator for ExportsIterator<I> {
// We can easily calculate the remaining number of iterations.
fn len(&self) -> usize {
self.size
}
}
impl<I: Iterator<Item = ExportType> + Sized> ExportsIterator<I> {
/// Get only the functions
pub fn functions(self) -> impl Iterator<Item = ExportType<FunctionType>> + 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<Item = ExportType<MemoryType>> + 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<Item = ExportType<TableType>> + 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<Item = ExportType<GlobalType>> + Sized {
self.iter.filter_map(|extern_| match extern_.ty() {
ExternType::Global(ty) => Some(ExportType::new(extern_.name(), ty.clone())),
_ => None,
})
}
}
impl<I: Iterator<Item = ExportType> + Sized> Iterator for ExportsIterator<I> {
type Item = ExportType;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}

View File

@@ -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 `<T>` 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<T = ExternType> {
name: String,
ty: ExternType,
ty: T,
}
impl ExportType {
impl<T> ExportType<T> {
/// 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
}
}