mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-18 06:19:12 +00:00
197 lines
4.5 KiB
Rust
197 lines
4.5 KiB
Rust
//! This module permits to create native functions
|
|
//! easily in Rust, thanks to its advanced typing system.
|
|
|
|
use crate::types::Type;
|
|
use crate::values::Value;
|
|
|
|
/// `NativeWasmType` represents a native Wasm type.
|
|
/// It uses the Rust Type system to automatically detect the
|
|
/// Wasm type associated with a native Rust type.
|
|
///
|
|
/// ```
|
|
/// use wasm_common::{NativeWasmType, Type};
|
|
///
|
|
/// let wasm_type = i32::WASM_TYPE;
|
|
/// assert_eq!(wasm_type, Type::I32);
|
|
/// ```
|
|
///
|
|
/// > Note: This strategy will be needed later to
|
|
/// > automatically detect the signature of a Rust function.
|
|
pub trait NativeWasmType: Sized {
|
|
/// The ABI for this type (i32, i64, f32, f64)
|
|
type Abi: Copy + std::fmt::Debug;
|
|
|
|
/// Type for this `NativeWasmType`.
|
|
const WASM_TYPE: Type;
|
|
|
|
#[doc(hidden)]
|
|
fn from_abi(abi: Self::Abi) -> Self;
|
|
|
|
#[doc(hidden)]
|
|
fn into_abi(self) -> Self::Abi;
|
|
|
|
/// Convert self to i128 binary representation.
|
|
fn to_binary(self) -> i128;
|
|
|
|
/// Convert self to a `Value`
|
|
fn to_value<T>(self) -> Value<T> {
|
|
let binary = self.to_binary();
|
|
unsafe { Value::read_value_from(&binary, Self::WASM_TYPE) }
|
|
}
|
|
|
|
/// Convert to self from i128 binary representation.
|
|
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
|
|
}
|
|
|
|
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;
|
|
|
|
#[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 _)
|
|
}
|
|
}
|
|
|
|
#[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);
|
|
}
|
|
}
|
|
|
|
// pub trait IntegerAtomic
|
|
// where
|
|
// Self: Sized
|
|
// {
|
|
// type Primitive;
|
|
|
|
// fn add(&self, other: Self::Primitive) -> Self::Primitive;
|
|
// fn sub(&self, other: Self::Primitive) -> Self::Primitive;
|
|
// fn and(&self, other: Self::Primitive) -> Self::Primitive;
|
|
// fn or(&self, other: Self::Primitive) -> Self::Primitive;
|
|
// fn xor(&self, other: Self::Primitive) -> Self::Primitive;
|
|
// fn load(&self) -> Self::Primitive;
|
|
// fn store(&self, other: Self::Primitive) -> Self::Primitive;
|
|
// fn compare_exchange(&self, expected: Self::Primitive, new: Self::Primitive) -> Self::Primitive;
|
|
// fn swap(&self, other: Self::Primitive) -> Self::Primitive;
|
|
// }
|
|
|
|
/// Trait for a Value type. A Value type is a type that is always valid and may
|
|
/// be safely copied.
|
|
///
|
|
/// That is, for all possible bit patterns a valid Value type can be constructed
|
|
/// from those bits.
|
|
///
|
|
/// Concretely a `u32` is a Value type because every combination of 32 bits is
|
|
/// a valid `u32`. However a `bool` is _not_ a Value type because any bit patterns
|
|
/// other than `0` and `1` are invalid in Rust and may cause undefined behavior if
|
|
/// a `bool` is constructed from those bytes.
|
|
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);
|