use wasmer_types::{NativeWasmType, RawValue, Type};
use wasmer_vm::{VMExternRef, VMFuncRef};
use crate::{ExternRef, Function};
use super::store::AsStoreMut;
pub trait NativeWasmTypeInto: NativeWasmType + Sized {
#[doc(hidden)]
fn into_abi(self, store: &mut impl AsStoreMut) -> Self::Abi;
#[doc(hidden)]
unsafe fn from_abi(store: &mut impl AsStoreMut, abi: Self::Abi) -> Self;
fn into_raw(self, store: &mut impl AsStoreMut) -> RawValue;
unsafe fn from_raw(store: &mut impl AsStoreMut, raw: RawValue) -> Self;
}
impl NativeWasmTypeInto for i32 {
#[inline]
unsafe fn from_abi(_store: &mut impl AsStoreMut, abi: Self::Abi) -> Self {
abi
}
#[inline]
fn into_abi(self, _store: &mut impl AsStoreMut) -> Self::Abi {
self
}
#[inline]
fn into_raw(self, _store: &mut impl AsStoreMut) -> RawValue {
RawValue { i32: self }
}
#[inline]
unsafe fn from_raw(_store: &mut impl AsStoreMut, raw: RawValue) -> Self {
raw.i32
}
}
impl NativeWasmTypeInto for i64 {
#[inline]
unsafe fn from_abi(_store: &mut impl AsStoreMut, abi: Self::Abi) -> Self {
abi
}
#[inline]
fn into_abi(self, _store: &mut impl AsStoreMut) -> Self::Abi {
self
}
#[inline]
fn into_raw(self, _store: &mut impl AsStoreMut) -> RawValue {
RawValue { i64: self }
}
#[inline]
unsafe fn from_raw(_store: &mut impl AsStoreMut, raw: RawValue) -> Self {
raw.i64
}
}
impl NativeWasmTypeInto for f32 {
#[inline]
unsafe fn from_abi(_store: &mut impl AsStoreMut, abi: Self::Abi) -> Self {
abi
}
#[inline]
fn into_abi(self, _store: &mut impl AsStoreMut) -> Self::Abi {
self
}
#[inline]
fn into_raw(self, _store: &mut impl AsStoreMut) -> RawValue {
RawValue { f32: self }
}
#[inline]
unsafe fn from_raw(_store: &mut impl AsStoreMut, raw: RawValue) -> Self {
raw.f32
}
}
impl NativeWasmTypeInto for f64 {
#[inline]
unsafe fn from_abi(_store: &mut impl AsStoreMut, abi: Self::Abi) -> Self {
abi
}
#[inline]
fn into_abi(self, _store: &mut impl AsStoreMut) -> Self::Abi {
self
}
#[inline]
fn into_raw(self, _store: &mut impl AsStoreMut) -> RawValue {
RawValue { f64: self }
}
#[inline]
unsafe fn from_raw(_store: &mut impl AsStoreMut, raw: RawValue) -> Self {
raw.f64
}
}
impl NativeWasmTypeInto for u128 {
#[inline]
unsafe fn from_abi(_store: &mut impl AsStoreMut, abi: Self::Abi) -> Self {
abi
}
#[inline]
fn into_abi(self, _store: &mut impl AsStoreMut) -> Self::Abi {
self
}
#[inline]
fn into_raw(self, _store: &mut impl AsStoreMut) -> RawValue {
RawValue { u128: self }
}
#[inline]
unsafe fn from_raw(_store: &mut impl AsStoreMut, raw: RawValue) -> Self {
raw.u128
}
}
impl NativeWasmType for ExternRef {
const WASM_TYPE: Type = Type::ExternRef;
type Abi = usize;
}
impl NativeWasmTypeInto for Option<ExternRef> {
#[inline]
unsafe fn from_abi(store: &mut impl AsStoreMut, abi: Self::Abi) -> Self {
VMExternRef::from_raw(RawValue { externref: abi })
.map(|e| ExternRef::from_vm_externref(store, e))
}
#[inline]
fn into_abi(self, _store: &mut impl AsStoreMut) -> Self::Abi {
self.map_or(0, |e| unsafe { e.vm_externref().into_raw().externref })
}
#[inline]
fn into_raw(self, _store: &mut impl AsStoreMut) -> RawValue {
self.map_or(RawValue { externref: 0 }, |e| e.vm_externref().into_raw())
}
#[inline]
unsafe fn from_raw(store: &mut impl AsStoreMut, raw: RawValue) -> Self {
VMExternRef::from_raw(raw).map(|e| ExternRef::from_vm_externref(store, e))
}
}
impl NativeWasmType for Function {
const WASM_TYPE: Type = Type::FuncRef;
type Abi = usize;
}
impl NativeWasmTypeInto for Option<Function> {
#[inline]
unsafe fn from_abi(store: &mut impl AsStoreMut, abi: Self::Abi) -> Self {
VMFuncRef::from_raw(RawValue { funcref: abi }).map(|f| Function::from_vm_funcref(store, f))
}
#[inline]
fn into_abi(self, store: &mut impl AsStoreMut) -> Self::Abi {
self.map_or(0, |f| unsafe { f.vm_funcref(store).into_raw().externref })
}
#[inline]
fn into_raw(self, store: &mut impl AsStoreMut) -> RawValue {
self.map_or(RawValue { externref: 0 }, |e| {
e.vm_funcref(store).into_raw()
})
}
#[inline]
unsafe fn from_raw(store: &mut impl AsStoreMut, raw: RawValue) -> Self {
VMFuncRef::from_raw(raw).map(|f| Function::from_vm_funcref(store, f))
}
}
#[cfg(test)]
mod test_native_type {
use super::*;
use wasmer_types::Type;
#[test]
fn test_wasm_types() {
assert_eq!(i32::WASM_TYPE, Type::I32);
assert_eq!(i64::WASM_TYPE, Type::I64);
assert_eq!(f32::WASM_TYPE, Type::F32);
assert_eq!(f64::WASM_TYPE, Type::F64);
assert_eq!(u128::WASM_TYPE, Type::V128);
}
}