Implement Exportable for NativeFunc

This commit is contained in:
Mark McCaskey
2020-06-08 16:07:22 -07:00
parent e2b6041a65
commit 8530e5eb55
9 changed files with 61 additions and 60 deletions

View File

@@ -1,11 +1,13 @@
use crate::externals::{Extern, Function, Global, Memory, Table};
use crate::import_object::LikeNamespace;
use crate::native::NativeFunc;
use indexmap::IndexMap;
use std::{
iter::{ExactSizeIterator, FromIterator},
sync::Arc,
};
use thiserror::Error;
use wasm_common::WasmTypeList;
use wasmer_runtime::Export;
/// The `ExportError` can happen when trying to get a specific
@@ -89,7 +91,7 @@ impl Exports {
///
/// If you want to get an export dynamically handling manually
/// type checking manually, please use `get_extern`.
pub fn get<'a, T: Exportable<'a>>(&'a self, name: &str) -> Result<&T, ExportError> {
pub fn get<'a, T: Exportable<'a>>(&'a self, name: &str) -> Result<T, ExportError> {
match self.map.get(name) {
None => Err(ExportError::Missing(name.to_string())),
Some(extern_) => T::get_self_from_extern(extern_),
@@ -97,32 +99,36 @@ impl Exports {
}
/// Get an export as a `Global`.
pub fn get_global(&self, name: &str) -> Result<&Global, ExportError> {
pub fn get_global(&self, name: &str) -> Result<Global, ExportError> {
self.get(name)
}
/// Get an export as a `Memory`.
pub fn get_memory(&self, name: &str) -> Result<&Memory, ExportError> {
pub fn get_memory(&self, name: &str) -> Result<Memory, ExportError> {
self.get(name)
}
/// Get an export as a `Table`.
pub fn get_table(&self, name: &str) -> Result<&Table, ExportError> {
pub fn get_table(&self, name: &str) -> Result<Table, ExportError> {
self.get(name)
}
/// Get an export as a `Func`.
pub fn get_function(&self, name: &str) -> Result<&Function, ExportError> {
pub fn get_function(&self, name: &str) -> Result<Function, ExportError> {
self.get(name)
}
/*
/// Get an export as a `Func`.
pub fn get_native_function::<Args, Rets>(&self, name: &str) -> Result<&NativeFunction, ExportError> {
// TODO:
//self.get(name)
/// Get an export as a `NativeFunc`.
pub fn get_native_function<Args, Rets>(
&self,
name: &str,
) -> Result<NativeFunc<Args, Rets>, ExportError>
where
Args: WasmTypeList,
Rets: WasmTypeList,
{
self.get(name)
}
*/
/// Get an export as an `Extern`.
pub fn get_extern(&self, name: &str) -> Option<&Extern> {
@@ -250,5 +256,5 @@ pub trait Exportable<'a>: Sized {
/// from an [`Instance`] by name.
///
/// [`Instance`]: crate::Instance
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError>;
fn get_self_from_extern(_extern: &'a Extern) -> Result<Self, ExportError>;
}

View File

@@ -317,9 +317,9 @@ impl<'a> Exportable<'a> for Function {
fn to_export(&self) -> Export {
self.exported.clone().into()
}
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> {
fn get_self_from_extern(_extern: &'a Extern) -> Result<Self, ExportError> {
match _extern {
Extern::Function(func) => Ok(func),
Extern::Function(func) => Ok(func.clone()),
_ => Err(ExportError::IncompatibleType),
}
}

View File

@@ -130,9 +130,9 @@ impl<'a> Exportable<'a> for Global {
self.exported.clone().into()
}
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> {
fn get_self_from_extern(_extern: &'a Extern) -> Result<Self, ExportError> {
match _extern {
Extern::Global(global) => Ok(global),
Extern::Global(global) => Ok(global.clone()),
_ => Err(ExportError::IncompatibleType),
}
}

View File

@@ -137,9 +137,9 @@ impl<'a> Exportable<'a> for Memory {
fn to_export(&self) -> Export {
self.exported.clone().into()
}
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> {
fn get_self_from_extern(_extern: &'a Extern) -> Result<Self, ExportError> {
match _extern {
Extern::Memory(memory) => Ok(memory),
Extern::Memory(memory) => Ok(memory.clone()),
_ => Err(ExportError::IncompatibleType),
}
}

View File

@@ -51,9 +51,9 @@ impl<'a> Exportable<'a> for Extern {
}
}
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> {
fn get_self_from_extern(_extern: &'a Extern) -> Result<Self, ExportError> {
// Since this is already an extern, we can just return it.
Ok(_extern)
Ok(_extern.clone())
}
}

View File

@@ -158,9 +158,9 @@ impl<'a> Exportable<'a> for Table {
fn to_export(&self) -> Export {
self.exported.clone().into()
}
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> {
fn get_self_from_extern(_extern: &'a Extern) -> Result<Self, ExportError> {
match _extern {
Extern::Table(table) => Ok(table),
Extern::Table(table) => Ok(table.clone()),
_ => Err(ExportError::IncompatibleType),
}
}

View File

@@ -4,10 +4,10 @@ use std::marker::PhantomData;
use crate::exports::{ExportError, Exportable};
use crate::externals::function::{FunctionDefinition, WasmFunctionDefinition};
use crate::{Extern, Function, FunctionType, RuntimeError, Store};
use crate::{Extern, Function, FunctionType, Store};
use wasm_common::{NativeWasmType, WasmExternType, WasmTypeList};
use wasmer_runtime::{
wasmer_call_trampoline, ExportFunction, VMContext, VMFunctionBody, VMFunctionKind, VMTrampoline,
wasmer_call_trampoline, Export, ExportFunction, VMContext, VMFunctionBody, VMFunctionKind,
};
#[derive(Clone)]
@@ -15,29 +15,6 @@ pub struct UnprovidedArgs;
#[derive(Clone)]
pub struct UnprovidedRets;
/// This is just an empty trait to constrict that types that
/// can be put into the third/fourth (depending if you include lifetimes)
/// of the `NativeFunc` struct.
pub trait Kind {}
/// TODO(lachlan): Naming TBD.
/// This contains the trampoline and invoke functions for a specific signature,
/// as well as the environment that the invoke function may or may not require.
#[derive(Copy, Clone)]
pub struct Wasm {
pub(crate) trampoline: VMTrampoline,
//pub(crate) invoke: Invoke,
//pub(crate) invoke_env: Option<NonNull<c_void>>,
}
impl Kind for Wasm {}
/// This type, as part of the `NativeFunc` type signature, represents a function that is created
/// by the host.
pub struct Host(());
impl Kind for Host {}
pub struct NativeFunc<'a, Args = UnprovidedArgs, Rets = UnprovidedRets> {
definition: FunctionDefinition,
store: Store,
@@ -69,35 +46,53 @@ impl<'a, Args, Rets> NativeFunc<'a, Args, Rets> {
}
}
/*
impl<'a, Args, Rets> Exportable for NativeFunc<'a, Args, Rets>
impl<'a, Args, Rets> Exportable<'a> for NativeFunc<'a, Args, Rets>
where
Args: WasmTypeList,
Rets: WasmTypeList,
{
fn to_export(&self) -> Export {
todo!("implement this")
let ef: ExportFunction = self.into();
ef.into()
}
// Cannot be implemented because of the return type `&Self` TODO:
fn get_self_from_extern(extern_: &'a Extern) -> Result<&'a Self, ExportError> {
fn get_self_from_extern(extern_: &'a Extern) -> Result<Self, ExportError> {
match extern_ {
// TODO: review error return type in failure of `f.native()`
Extern::Function(f) => f.native().ok_or_else(|| ExportError::IncompatibleType),
Extern::Function(f) => f
.clone()
.native()
.ok_or_else(|| ExportError::IncompatibleType),
_ => Err(ExportError::IncompatibleType),
}
}
}
*/
impl<'a, Args, Rets> From<&NativeFunc<'a, Args, Rets>> for ExportFunction
where
Args: WasmTypeList,
Rets: WasmTypeList,
{
fn from(other: &NativeFunc<'a, Args, Rets>) -> Self {
let signature = FunctionType::new(Args::wasm_types(), Rets::wasm_types());
Self {
address: other.address,
vmctx: other.vmctx,
signature,
kind: other.arg_kind,
}
}
}
impl<'a, Args, Rets> From<NativeFunc<'a, Args, Rets>> for Function
where
Args: WasmTypeList,
Rets: WasmTypeList,
{
fn from(other: NativeFunc<'a, Args, Rets>) -> Function {
fn from(other: NativeFunc<'a, Args, Rets>) -> Self {
let signature = FunctionType::new(Args::wasm_types(), Rets::wasm_types());
Function {
Self {
store: other.store,
definition: other.definition,
owned_by_store: true, // todo

View File

@@ -111,10 +111,10 @@ impl Wasi {
let instance = Instance::new(&module, &import_object)?;
let memory: &Memory = instance.exports.get("memory")?;
wasi_env.set_memory(memory);
let memory: Memory = instance.exports.get("memory")?;
wasi_env.set_memory(&memory);
let start: &Function = instance.exports.get("_start")?;
let start: Function = instance.exports.get("_start")?;
start
.call(&[])

View File

@@ -341,7 +341,7 @@ impl Wast {
args: &[Val],
) -> Result<Vec<Val>> {
let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?;
let func: &Function = instance.exports.get(field)?;
let func: Function = instance.exports.get(field)?;
match func.call(args) {
Ok(result) => Ok(result.into()),
Err(e) => Err(e.into()),
@@ -351,7 +351,7 @@ impl Wast {
/// Get the value of an exported global from an instance.
fn get(&mut self, instance_name: Option<&str>, field: &str) -> Result<Vec<Val>> {
let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?;
let global: &Global = instance.exports.get(field)?;
let global: Global = instance.exports.get(field)?;
Ok(vec![global.get()])
}