use crate::extern_ref::VMExternRef;
use crate::lib::std::fmt;
use crate::types::Type;
use crate::values::{Value, WasmValueType};
pub trait NativeWasmType: Sized {
type Abi: Copy + fmt::Debug;
const WASM_TYPE: Type;
#[doc(hidden)]
fn from_abi(abi: Self::Abi) -> Self;
#[doc(hidden)]
fn into_abi(self) -> Self::Abi;
fn to_binary(self) -> i128;
fn to_value<T: WasmValueType>(self) -> Value<T> {
let binary = self.to_binary();
let hack = 3;
unsafe { Value::read_value_from(&hack, &binary, Self::WASM_TYPE) }
}
fn from_binary(binary: i128) -> Self;
}
impl NativeWasmType for i32 {
const WASM_TYPE: Type = Type::I32;
type Abi = Self;
#[inline]
fn from_abi(abi: Self::Abi) -> Self {
abi
}
#[inline]
fn into_abi(self) -> Self::Abi {
self
}
#[inline]
fn to_binary(self) -> i128 {
self as _
}
#[inline]
fn from_binary(bits: i128) -> Self {
bits as _
}
}
impl NativeWasmType for i64 {
const WASM_TYPE: Type = Type::I64;
type Abi = Self;
#[inline]
fn from_abi(abi: Self::Abi) -> Self {
abi
}
#[inline]
fn into_abi(self) -> Self::Abi {
self
}
#[inline]
fn to_binary(self) -> i128 {
self as _
}
#[inline]
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
}
#[inline]
fn to_binary(self) -> i128 {
self.to_bits() as _
}
#[inline]
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
}
#[inline]
fn to_binary(self) -> i128 {
self.to_bits() as _
}
#[inline]
fn from_binary(bits: i128) -> Self {
Self::from_bits(bits as _)
}
}
impl NativeWasmType for u128 {
const WASM_TYPE: Type = Type::V128;
type Abi = Self;
#[inline]
fn from_abi(abi: Self::Abi) -> Self {
abi
}
#[inline]
fn into_abi(self) -> Self::Abi {
self
}
#[inline]
fn to_binary(self) -> i128 {
self as _
}
#[inline]
fn from_binary(bits: i128) -> Self {
bits as _
}
}
impl NativeWasmType for VMExternRef {
const WASM_TYPE: Type = Type::ExternRef;
type Abi = Self;
#[inline]
fn from_abi(abi: Self::Abi) -> Self {
abi
}
#[inline]
fn into_abi(self) -> Self::Abi {
self
}
#[inline]
fn to_binary(self) -> i128 {
self.to_binary()
}
#[inline]
fn from_binary(bits: i128) -> Self {
unsafe { Self::from_binary(bits) }
}
}
#[cfg(test)]
mod test_native_type {
use super::*;
use crate::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);
}
#[test]
fn test_roundtrip() {
assert_eq!(i32::from_binary(42i32.to_binary()), 42i32);
assert_eq!(i64::from_binary(42i64.to_binary()), 42i64);
assert_eq!(f32::from_binary(42f32.to_binary()), 42f32);
assert_eq!(f64::from_binary(42f64.to_binary()), 42f64);
assert_eq!(u128::from_binary(42u128.to_binary()), 42u128);
}
}
pub unsafe trait ValueType: Copy
where
Self: Sized,
{
}
macro_rules! impl_value_type_for {
( $($type:ty),* ) => {
$(
unsafe impl ValueType for $type {}
)*
};
}
impl_value_type_for!(u8, i8, u16, i16, u32, i32, u64, i64, f32, f64);