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 thiserror::Error;
use wasmer_compiler::{CompileError, WasmError}; use wasmer_compiler::{CompileError, WasmError};
use wasmer_jit::{CompiledModule, DeserializeError, Resolver, SerializeError}; use wasmer_jit::{CompiledModule, DeserializeError, Resolver, SerializeError};
use wasmer_runtime::InstanceHandle; use wasmer_runtime::{ExportsIterator, InstanceHandle, Module as ModuleInfo};
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum IoCompileError { pub enum IoCompileError {
@@ -274,11 +274,21 @@ impl Module {
/// export.ty(); /// 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() self.compiled.module().exports()
} }
pub fn store(&self) -> &Store { pub fn store(&self) -> &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. /// 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 /// are export names, and the values are export declarations which can be
/// resolved `lookup_by_declaration`. /// resolved `lookup_by_declaration`.
pub fn exports(&self) -> indexmap::map::Iter<String, ExportIndex> { 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::instance::InstanceHandle;
pub use crate::memory::LinearMemory; pub use crate::memory::LinearMemory;
pub use crate::mmap::Mmap; 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::probestack::PROBESTACK;
pub use crate::sig_registry::SignatureRegistry; pub use crate::sig_registry::SignatureRegistry;
pub use crate::table::Table; pub use crate::table::Table;

View File

@@ -5,6 +5,7 @@ use indexmap::IndexMap;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt; use std::fmt;
use std::iter::ExactSizeIterator;
use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
use std::sync::Arc; use std::sync::Arc;
use wasm_common::entity::{EntityRef, PrimaryMap}; use wasm_common::entity::{EntityRef, PrimaryMap};
@@ -134,7 +135,7 @@ pub struct Module {
/// WebAssembly function signatures. /// WebAssembly function signatures.
pub signatures: PrimaryMap<SignatureIndex, FunctionType>, pub signatures: PrimaryMap<SignatureIndex, FunctionType>,
/// Types of functions (imported and local). /// WebAssembly functions (imported and local).
pub functions: PrimaryMap<FunctionIndex, SignatureIndex>, pub functions: PrimaryMap<FunctionIndex, SignatureIndex>,
/// WebAssembly tables (imported and local). /// WebAssembly tables (imported and local).
@@ -206,8 +207,8 @@ impl Module {
} }
/// Get the export types of the module /// Get the export types of the module
pub fn exports<'a>(&'a self) -> impl Iterator<Item = ExportType> + 'a { pub fn exports<'a>(&'a self) -> ExportsIterator<impl Iterator<Item = ExportType> + 'a> {
self.exports.iter().map(move |(name, export_index)| { let iter = self.exports.iter().map(move |(name, export_index)| {
let extern_type = match export_index { let extern_type = match export_index {
ExportIndex::Function(i) => { ExportIndex::Function(i) => {
let signature = self.functions.get(i.clone()).unwrap(); let signature = self.functions.get(i.clone()).unwrap();
@@ -228,7 +229,11 @@ impl Module {
} }
}; };
ExportType::new(name, extern_type) ExportType::new(name, extern_type)
}) });
ExportsIterator {
iter,
size: self.exports.len(),
}
} }
/// Get the export types of the module /// Get the export types of the module
@@ -348,3 +353,56 @@ impl fmt::Display for Module {
write!(f, "{}", self.name()) 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 /// [`Module::exports`](crate::Module::exports) accessor and describes what
/// names are exported from a wasm module and the type of the item that is /// names are exported from a wasm module and the type of the item that is
/// exported. /// 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)] #[derive(Debug, Clone)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct ExportType { pub struct ExportType<T = ExternType> {
name: String, 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 /// Creates a new export which is exported with the given `name` and has the
/// given `ty`. /// given `ty`.
pub fn new(name: &str, ty: ExternType) -> ExportType { pub fn new(name: &str, ty: T) -> Self {
ExportType { ExportType {
name: name.to_string(), name: name.to_string(),
ty, ty,
@@ -525,7 +529,7 @@ impl ExportType {
} }
/// Returns the type of this export. /// Returns the type of this export.
pub fn ty(&self) -> &ExternType { pub fn ty(&self) -> &T {
&self.ty &self.ty
} }
} }