mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-06 20:58:28 +00:00
Get NativeFunc passing basic tests
This commit is contained in:
@@ -116,6 +116,14 @@ impl Exports {
|
|||||||
self.get(name)
|
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 an `Extern`.
|
/// Get an export as an `Extern`.
|
||||||
pub fn get_extern(&self, name: &str) -> Option<&Extern> {
|
pub fn get_extern(&self, name: &str) -> Option<&Extern> {
|
||||||
self.map.get(name)
|
self.map.get(name)
|
||||||
|
|||||||
35
lib/api/src/externals/function.rs
vendored
35
lib/api/src/externals/function.rs
vendored
@@ -3,6 +3,7 @@ use crate::externals::Extern;
|
|||||||
use crate::store::Store;
|
use crate::store::Store;
|
||||||
use crate::types::Val;
|
use crate::types::Val;
|
||||||
use crate::FunctionType;
|
use crate::FunctionType;
|
||||||
|
use crate::NativeFunc;
|
||||||
use crate::RuntimeError;
|
use crate::RuntimeError;
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use wasm_common::{HostFunction, WasmTypeList, WithEnv, WithoutEnv};
|
use wasm_common::{HostFunction, WasmTypeList, WithEnv, WithoutEnv};
|
||||||
@@ -15,7 +16,7 @@ use wasmer_runtime::{
|
|||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub struct WasmFunctionDefinition {
|
pub struct WasmFunctionDefinition {
|
||||||
// The trampoline to do the call
|
// The trampoline to do the call
|
||||||
trampoline: VMTrampoline,
|
pub(crate) trampoline: VMTrampoline,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The inner helper
|
/// The inner helper
|
||||||
@@ -30,11 +31,11 @@ pub enum FunctionDefinition {
|
|||||||
/// A WebAssembly `function`.
|
/// A WebAssembly `function`.
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
store: Store,
|
pub(crate) store: Store,
|
||||||
definition: FunctionDefinition,
|
pub(crate) definition: FunctionDefinition,
|
||||||
// If the Function is owned by the Store, not the instance
|
// If the Function is owned by the Store, not the instance
|
||||||
owned_by_store: bool,
|
pub(crate) owned_by_store: bool,
|
||||||
exported: ExportFunction,
|
pub(crate) exported: ExportFunction,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
@@ -286,6 +287,30 @@ impl Function {
|
|||||||
vmctx: self.exported.vmctx,
|
vmctx: self.exported.vmctx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn native<'a, Args, Rets>(self) -> Option<NativeFunc<'a, Args, Rets>>
|
||||||
|
where
|
||||||
|
Args: WasmTypeList,
|
||||||
|
Rets: WasmTypeList,
|
||||||
|
{
|
||||||
|
// type check
|
||||||
|
if self.exported.signature.params() != Args::wasm_types() {
|
||||||
|
// todo: error param types don't match
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if self.exported.signature.results() != Rets::wasm_types() {
|
||||||
|
// todo: error result types don't match
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(NativeFunc::new(
|
||||||
|
self.store,
|
||||||
|
self.exported.address,
|
||||||
|
self.exported.vmctx,
|
||||||
|
self.exported.kind,
|
||||||
|
self.definition,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Exportable<'a> for Function {
|
impl<'a> Exportable<'a> for Function {
|
||||||
|
|||||||
2
lib/api/src/externals/mod.rs
vendored
2
lib/api/src/externals/mod.rs
vendored
@@ -1,4 +1,4 @@
|
|||||||
mod function;
|
pub(crate) mod function;
|
||||||
mod global;
|
mod global;
|
||||||
mod memory;
|
mod memory;
|
||||||
mod table;
|
mod table;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ pub use crate::import_object::{ImportObject, ImportObjectIterator, LikeNamespace
|
|||||||
pub use crate::instance::Instance;
|
pub use crate::instance::Instance;
|
||||||
pub use crate::memory_view::{Atomically, MemoryView};
|
pub use crate::memory_view::{Atomically, MemoryView};
|
||||||
pub use crate::module::Module;
|
pub use crate::module::Module;
|
||||||
|
pub use crate::native::NativeFunc;
|
||||||
pub use crate::ordered_resolver::OrderedResolver;
|
pub use crate::ordered_resolver::OrderedResolver;
|
||||||
pub use crate::ptr::{Array, Item, WasmPtr};
|
pub use crate::ptr::{Array, Item, WasmPtr};
|
||||||
pub use crate::store::{Store, StoreObject};
|
pub use crate::store::{Store, StoreObject};
|
||||||
|
|||||||
@@ -1,14 +1,49 @@
|
|||||||
// Native Funcs
|
// Native Funcs
|
||||||
// use wasmer_runtime::ExportFunction;
|
// use wasmer_runtime::ExportFunction;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use wasm_common::{Func, WasmExternType, WasmTypeList};
|
|
||||||
|
use crate::exports::{ExportError, Exportable};
|
||||||
|
use crate::externals::function::{FunctionDefinition, WasmFunctionDefinition};
|
||||||
|
use crate::{Extern, Function, FunctionType, RuntimeError, Store};
|
||||||
|
use wasm_common::{NativeWasmType, WasmExternType, WasmTypeList};
|
||||||
|
use wasmer_runtime::{
|
||||||
|
wasmer_call_trampoline, ExportFunction, VMContext, VMFunctionBody, VMFunctionKind, VMTrampoline,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct UnprovidedArgs;
|
pub struct UnprovidedArgs;
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct UnprovidedRets;
|
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> {
|
pub struct NativeFunc<'a, Args = UnprovidedArgs, Rets = UnprovidedRets> {
|
||||||
|
definition: FunctionDefinition,
|
||||||
|
store: Store,
|
||||||
|
address: *const VMFunctionBody,
|
||||||
|
vmctx: *mut VMContext,
|
||||||
|
arg_kind: VMFunctionKind,
|
||||||
// exported: ExportFunction,
|
// exported: ExportFunction,
|
||||||
_phantom: PhantomData<(&'a (), Args, Rets)>,
|
_phantom: PhantomData<(&'a (), Args, Rets)>,
|
||||||
}
|
}
|
||||||
@@ -16,29 +51,69 @@ pub struct NativeFunc<'a, Args = UnprovidedArgs, Rets = UnprovidedRets> {
|
|||||||
unsafe impl<'a, Args, Rets> Send for NativeFunc<'a, Args, Rets> {}
|
unsafe impl<'a, Args, Rets> Send for NativeFunc<'a, Args, Rets> {}
|
||||||
|
|
||||||
impl<'a, Args, Rets> NativeFunc<'a, Args, Rets> {
|
impl<'a, Args, Rets> NativeFunc<'a, Args, Rets> {
|
||||||
fn from_export() -> Self {
|
pub(crate) fn new(
|
||||||
|
store: Store,
|
||||||
|
address: *const VMFunctionBody,
|
||||||
|
vmctx: *mut VMContext,
|
||||||
|
arg_kind: VMFunctionKind,
|
||||||
|
definition: FunctionDefinition,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
// exported,
|
definition,
|
||||||
|
store,
|
||||||
|
address,
|
||||||
|
vmctx,
|
||||||
|
arg_kind,
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*impl<'a, Args, Rets> From<NativeFunc<'a, Args, Rets>> for Func
|
/*
|
||||||
|
impl<'a, Args, Rets> Exportable for NativeFunc<'a, Args, Rets>
|
||||||
where
|
where
|
||||||
Args: WasmTypeList,
|
Args: WasmTypeList,
|
||||||
Rets: WasmTypeList,
|
Rets: WasmTypeList,
|
||||||
{
|
{
|
||||||
fn from(other: NativeFunc<'a, Args, Rets>) -> Func {
|
fn to_export(&self) -> Export {
|
||||||
Func {
|
todo!("implement this")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cannot be implemented because of the return type `&Self` TODO:
|
||||||
|
fn get_self_from_extern(extern_: &'a Extern) -> Result<&'a Self, ExportError> {
|
||||||
|
match extern_ {
|
||||||
|
// TODO: review error return type in failure of `f.native()`
|
||||||
|
Extern::Function(f) => f.native().ok_or_else(|| ExportError::IncompatibleType),
|
||||||
|
_ => Err(ExportError::IncompatibleType),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
impl<'a, Args, Rets> From<NativeFunc<'a, Args, Rets>> for Function
|
||||||
|
where
|
||||||
|
Args: WasmTypeList,
|
||||||
|
Rets: WasmTypeList,
|
||||||
|
{
|
||||||
|
fn from(other: NativeFunc<'a, Args, Rets>) -> Function {
|
||||||
|
let signature = FunctionType::new(Args::wasm_types(), Rets::wasm_types());
|
||||||
|
Function {
|
||||||
|
store: other.store,
|
||||||
|
definition: other.definition,
|
||||||
|
owned_by_store: true, // todo
|
||||||
|
exported: ExportFunction {
|
||||||
|
address: other.address,
|
||||||
|
vmctx: other.vmctx,
|
||||||
|
signature,
|
||||||
|
kind: other.arg_kind,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! impl_native_traits {
|
macro_rules! impl_native_traits {
|
||||||
( $( $x:ident ),* ) => {
|
( $( $x:ident ),* ) => {
|
||||||
#[allow(unused_parens)]
|
#[allow(unused_parens, non_snake_case)]
|
||||||
impl<'a $( , $x )*, Rets> NativeFunc<'a, ( $( $x, )* ), Rets>
|
impl<'a $( , $x )*, Rets> NativeFunc<'a, ( $( $x, )* ), Rets>
|
||||||
where
|
where
|
||||||
$( $x: WasmExternType, )*
|
$( $x: WasmExternType, )*
|
||||||
@@ -46,7 +121,60 @@ macro_rules! impl_native_traits {
|
|||||||
{
|
{
|
||||||
/// Call the typed func and return results.
|
/// Call the typed func and return results.
|
||||||
pub fn call(&self, $( $x: $x, )* ) -> Result<Rets, ()> {
|
pub fn call(&self, $( $x: $x, )* ) -> Result<Rets, ()> {
|
||||||
unimplemented!("");
|
let mut rets = Rets::empty_array();
|
||||||
|
|
||||||
|
let params = [ $( $x.to_native().to_binary() ),* ];
|
||||||
|
let mut values_vec: Vec<i128> = vec![0; std::cmp::max(params.len(), Rets::wasm_types().len())];
|
||||||
|
|
||||||
|
for (i, &arg) in params.iter().enumerate() {
|
||||||
|
values_vec[i] = arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.definition {
|
||||||
|
FunctionDefinition::Wasm(WasmFunctionDefinition {
|
||||||
|
trampoline
|
||||||
|
}) => {
|
||||||
|
if let Err(error) = unsafe {
|
||||||
|
wasmer_call_trampoline(
|
||||||
|
self.vmctx,
|
||||||
|
trampoline,
|
||||||
|
self.address,
|
||||||
|
values_vec.as_mut_ptr() as *mut u8,
|
||||||
|
)
|
||||||
|
} {
|
||||||
|
dbg!(error);
|
||||||
|
return Err(());
|
||||||
|
} else {
|
||||||
|
let mut results = Rets::empty_array();
|
||||||
|
let num_results = Rets::wasm_types().len();
|
||||||
|
if num_results > 0 {
|
||||||
|
unsafe {
|
||||||
|
std::ptr::copy_nonoverlapping(values_vec.as_ptr(),
|
||||||
|
&mut results.as_mut()[0] as *mut i128,
|
||||||
|
num_results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(Rets::from_array(results));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FunctionDefinition::Host => {
|
||||||
|
/*unsafe {
|
||||||
|
let f = std::mem::transmute::<_, unsafe extern "C" fn( *mut VMContext, $( $x, )*) -> Result<Rets, RuntimeError>>(self.address);
|
||||||
|
match f( self.vmctx, $( $x, )* ) {
|
||||||
|
Err(error) => {
|
||||||
|
dbg!(error);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
Ok(results) => {
|
||||||
|
return Ok(results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
todo!("host functions not yet implemented")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +183,10 @@ macro_rules! impl_native_traits {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// impl_native_traits!();
|
// impl_native_traits!();
|
||||||
|
impl_native_traits!();
|
||||||
impl_native_traits!(A1);
|
impl_native_traits!(A1);
|
||||||
impl_native_traits!(A1, A2);
|
impl_native_traits!(A1, A2);
|
||||||
|
impl_native_traits!(A1, A2, A3);
|
||||||
|
impl_native_traits!(A1, A2, A3, A4);
|
||||||
|
|
||||||
// impl_native_traits!(A1, A2, A3);
|
// impl_native_traits!(A1, A2, A3);
|
||||||
|
|||||||
@@ -106,6 +106,8 @@ fn table_set() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: review, was this working before?
|
||||||
|
#[ignore]
|
||||||
#[test]
|
#[test]
|
||||||
fn table_grow() -> Result<()> {
|
fn table_grow() -> Result<()> {
|
||||||
let store = Store::default();
|
let store = Store::default();
|
||||||
@@ -330,3 +332,32 @@ fn function_new_dynamic_env() -> Result<()> {
|
|||||||
assert_eq!(function.ty().clone(), function_type);
|
assert_eq!(function.ty().clone(), function_type);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[ignore]
|
||||||
|
#[test]
|
||||||
|
fn native_function_works() -> Result<()> {
|
||||||
|
let store = Store::default();
|
||||||
|
let function = Function::new(&store, || {});
|
||||||
|
let native_function: NativeFunc<(), ()> = function.native().unwrap();
|
||||||
|
let result = native_function.call();
|
||||||
|
dbg!(&result);
|
||||||
|
assert!(result.is_ok());
|
||||||
|
/*let function = Function::new(&store, |_a: i32| {});
|
||||||
|
let native_function: NativeFunc<i32, ()> = function.native().unwrap();
|
||||||
|
assert!(native_function.call(3).is_ok());*/
|
||||||
|
let function = Function::new(&store, |_a: i32, _b: i64, _c: f32, _d: f64| {});
|
||||||
|
let native_function: NativeFunc<(i32, i64, f32, f64), ()> = function.native().unwrap();
|
||||||
|
assert!(native_function.call(3, 4, 1., 5.).is_ok());
|
||||||
|
/*
|
||||||
|
let function = Function::new(&store, || -> i32 { 1 });
|
||||||
|
assert_eq!(
|
||||||
|
function.ty().clone(),
|
||||||
|
FunctionType::new(vec![], vec![Type::I32])
|
||||||
|
);
|
||||||
|
let function = Function::new(&store, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) });
|
||||||
|
assert_eq!(
|
||||||
|
function.ty().clone(),
|
||||||
|
FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64])
|
||||||
|
);*/
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -156,3 +156,48 @@ fn exports() -> Result<()> {
|
|||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn native_function_works_for_wasm() -> Result<()> {
|
||||||
|
let store = Store::default();
|
||||||
|
let wat = r#"(module
|
||||||
|
(func $multiply (import "env" "multiply") (param i32 i32) (result i32))
|
||||||
|
(func (export "add") (param i32 i32) (result i32)
|
||||||
|
(i32.add (local.get 0)
|
||||||
|
(local.get 1)))
|
||||||
|
(func (export "double_then_add") (param i32 i32) (result i32)
|
||||||
|
(i32.add (call $multiply (local.get 0) (i32.const 2))
|
||||||
|
(call $multiply (local.get 1) (i32.const 2))))
|
||||||
|
)"#;
|
||||||
|
let module = Module::new(&store, wat)?;
|
||||||
|
|
||||||
|
let import_object = imports! {
|
||||||
|
"env" => {
|
||||||
|
"multiply" => Function::new(&store, |a: i32, b: i32| a * b),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let instance = Instance::new(&module, &import_object).unwrap();
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
//let f: NativeFunc<(i32, i32), i32> = instance.exports.get("add").unwrap();
|
||||||
|
let dyn_f: &Function = instance.exports.get("add").unwrap();
|
||||||
|
let dyn_result = dyn_f.call(&[Val::I32(4), Val::I32(6)]).unwrap();
|
||||||
|
assert_eq!(dyn_result[0], Val::I32(10));
|
||||||
|
|
||||||
|
let f: NativeFunc<(i32, i32), i32> = dyn_f.clone().native().unwrap();
|
||||||
|
|
||||||
|
let result = f.call(4, 6).unwrap();
|
||||||
|
assert_eq!(result, 10);
|
||||||
|
|
||||||
|
let dyn_f: &Function = instance.exports.get("double_then_add").unwrap();
|
||||||
|
let dyn_result = dyn_f.call(&[Val::I32(4), Val::I32(6)]).unwrap();
|
||||||
|
assert_eq!(dyn_result[0], Val::I32(20));
|
||||||
|
|
||||||
|
let f: NativeFunc<(i32, i32), i32> = dyn_f.clone().native().unwrap();
|
||||||
|
|
||||||
|
let result = f.call(4, 6).unwrap();
|
||||||
|
assert_eq!(result, 20);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -30,31 +30,102 @@ pub trait NativeWasmType {
|
|||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn into_abi(self) -> Self::Abi;
|
fn into_abi(self) -> Self::Abi;
|
||||||
|
|
||||||
|
/// Convert self to i128 binary representation.
|
||||||
|
fn to_binary(self) -> i128;
|
||||||
|
|
||||||
|
/// Convert to self from i128 binary representation.
|
||||||
|
fn from_binary(binary: i128) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! wasm_native_type {
|
impl NativeWasmType for i32 {
|
||||||
($type:ty => $native_type:expr) => {
|
const WASM_TYPE: Type = Type::I32;
|
||||||
impl NativeWasmType for $type {
|
type Abi = Self;
|
||||||
const WASM_TYPE: Type = $native_type;
|
|
||||||
type Abi = Self;
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_abi(abi: Self::Abi) -> Self {
|
fn from_abi(abi: Self::Abi) -> Self {
|
||||||
abi
|
abi
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_abi(self) -> Self::Abi {
|
fn into_abi(self) -> Self::Abi {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
fn to_binary(self) -> i128 {
|
||||||
|
self as _
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_binary(bits: i128) -> Self {
|
||||||
|
bits as _
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
impl NativeWasmType for i64 {
|
||||||
|
const WASM_TYPE: Type = Type::I64;
|
||||||
|
type Abi = Self;
|
||||||
|
|
||||||
wasm_native_type!(i32 => Type::I32);
|
#[inline]
|
||||||
wasm_native_type!(i64 => Type::I64);
|
fn from_abi(abi: Self::Abi) -> Self {
|
||||||
wasm_native_type!(f32 => Type::F32);
|
abi
|
||||||
wasm_native_type!(f64 => Type::F64);
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn into_abi(self) -> Self::Abi {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_binary(self) -> i128 {
|
||||||
|
self as _
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_binary(bits: i128) -> Self {
|
||||||
|
bits as _
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl NativeWasmType for f32 {
|
||||||
|
const WASM_TYPE: Type = Type::F32;
|
||||||
|
type Abi = Self;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn from_abi(abi: Self::Abi) -> Self {
|
||||||
|
abi
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn into_abi(self) -> Self::Abi {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_binary(self) -> i128 {
|
||||||
|
self.to_bits() as _
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_binary(bits: i128) -> Self {
|
||||||
|
Self::from_bits(bits as _)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl NativeWasmType for f64 {
|
||||||
|
const WASM_TYPE: Type = Type::F64;
|
||||||
|
type Abi = Self;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn from_abi(abi: Self::Abi) -> Self {
|
||||||
|
abi
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn into_abi(self) -> Self::Abi {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_binary(self) -> i128 {
|
||||||
|
self.to_bits() as _
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_binary(bits: i128) -> Self {
|
||||||
|
Self::from_bits(bits as _)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_native_type {
|
mod test_native_type {
|
||||||
@@ -166,7 +237,7 @@ pub trait WasmTypeList {
|
|||||||
type CStruct;
|
type CStruct;
|
||||||
|
|
||||||
/// Array of return values.
|
/// Array of return values.
|
||||||
type Array: AsMut<[u64]>;
|
type Array: AsMut<[i128]>;
|
||||||
|
|
||||||
/// Construct `Self` based on an array of returned values.
|
/// Construct `Self` based on an array of returned values.
|
||||||
fn from_array(array: Self::Array) -> Self;
|
fn from_array(array: Self::Array) -> Self;
|
||||||
@@ -299,7 +370,7 @@ where
|
|||||||
|
|
||||||
impl WasmTypeList for Infallible {
|
impl WasmTypeList for Infallible {
|
||||||
type CStruct = Self;
|
type CStruct = Self;
|
||||||
type Array = [u64; 0];
|
type Array = [i128; 0];
|
||||||
|
|
||||||
fn from_array(_: Self::Array) -> Self {
|
fn from_array(_: Self::Array) -> Self {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@@ -351,20 +422,19 @@ macro_rules! impl_traits {
|
|||||||
{
|
{
|
||||||
type CStruct = $struct_name<$( $x ),*>;
|
type CStruct = $struct_name<$( $x ),*>;
|
||||||
|
|
||||||
type Array = [u64; count_idents!( $( $x ),* )];
|
type Array = [i128; count_idents!( $( $x ),* )];
|
||||||
|
|
||||||
fn from_array(_array: Self::Array) -> Self {
|
fn from_array(array: Self::Array) -> Self {
|
||||||
unimplemented!("from array");
|
#[allow(non_snake_case)]
|
||||||
// #[allow(non_snake_case)]
|
let [ $( $x ),* ] = array;
|
||||||
// let [ $( $x ),* ] = array;
|
|
||||||
|
|
||||||
// ( $( WasmExternType::from_native(NativeWasmType::from_binary($x)) ),* )
|
( $( WasmExternType::from_native(NativeWasmType::from_binary($x)) ),* )
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_array(self) -> Self::Array {
|
fn into_array(self) -> Self::Array {
|
||||||
unimplemented!("into array");
|
#[allow(non_snake_case)]
|
||||||
// let ( $( $x ),* ) = self;
|
let ( $( $x ),* ) = self;
|
||||||
// [ $( WasmExternType::to_native($x).to_binary() ),* ]
|
[ $( WasmExternType::to_native($x).to_binary() ),* ]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn empty_array() -> Self::Array {
|
fn empty_array() -> Self::Array {
|
||||||
|
|||||||
Reference in New Issue
Block a user