wasmi_core/
typed.rs

1use crate::{UntypedVal, ValType, F32, F64, V128};
2
3/// Types that are associated to a static Wasm type.
4pub trait Typed {
5    /// The static associated Wasm type.
6    const TY: ValType;
7}
8macro_rules! impl_typed_for {
9    ( $( $ty:ty => $value_ty:expr );* $(;)? ) => {
10        $(
11            impl Typed for $ty {
12                const TY: ValType = $value_ty;
13            }
14        )*
15    };
16}
17impl_typed_for! {
18    bool => ValType::I32;
19    i8 => ValType::I32;
20    u8 => ValType::I32;
21    i16 => ValType::I32;
22    u16 => ValType::I32;
23    i32 => ValType::I32;
24    u32 => ValType::I32;
25    i64 => ValType::I64;
26    u64 => ValType::I64;
27    f32 => ValType::F32;
28    f64 => ValType::F64;
29    F32 => ValType::F32;
30    F64 => ValType::F64;
31    V128 => ValType::V128;
32}
33
34impl From<TypedVal> for UntypedVal {
35    fn from(typed_value: TypedVal) -> Self {
36        typed_value.value
37    }
38}
39
40/// An [`UntypedVal`] with its assumed [`ValType`].
41///
42/// # Note
43///
44/// We explicitly do not make use of the existing [`Val`]
45/// abstraction since [`Val`] is optimized towards being a
46/// user facing type whereas [`TypedVal`] is focusing on
47/// performance and efficiency in computations.
48///
49/// [`Val`]: [`crate::core::Value`]
50#[derive(Debug, Copy, Clone, PartialEq, Eq)]
51pub struct TypedVal {
52    /// The type of the value.
53    ty: ValType,
54    /// The underlying raw value.
55    value: UntypedVal,
56}
57
58impl TypedVal {
59    /// Create a new [`TypedVal`].
60    pub fn new(ty: ValType, value: UntypedVal) -> Self {
61        Self { ty, value }
62    }
63
64    /// Returns the [`ValType`] of the [`TypedVal`].
65    pub fn ty(&self) -> ValType {
66        self.ty
67    }
68
69    /// Returns the [`UntypedVal`] of the [`TypedVal`].
70    pub fn untyped(&self) -> UntypedVal {
71        self.value
72    }
73}
74
75impl<T> From<T> for TypedVal
76where
77    T: Typed + Into<UntypedVal>,
78{
79    fn from(value: T) -> Self {
80        Self::new(<T as Typed>::TY, value.into())
81    }
82}
83
84macro_rules! impl_from_typed_value_for {
85    ( $( $( #[$attr:meta] )* impl From<TypedVal> for $ty:ty );* $(;)? ) => {
86        $(
87            $( #[$attr] )*
88            impl From<TypedVal> for $ty {
89                fn from(typed_value: TypedVal) -> Self {
90                    // # Note
91                    //
92                    // We only use a `debug_assert` here instead of a proper `assert`
93                    // since the whole translation process assumes that Wasm validation
94                    // was already performed and thus type checking does not necessarily
95                    // need to happen redundantly outside of debug builds.
96                    debug_assert!(matches!(typed_value.ty, <$ty as Typed>::TY));
97                    Self::from(typed_value.value)
98                }
99            }
100        )*
101    };
102}
103impl_from_typed_value_for! {
104    impl From<TypedVal> for bool;
105    impl From<TypedVal> for i32;
106    impl From<TypedVal> for u32;
107    impl From<TypedVal> for i64;
108    impl From<TypedVal> for u64;
109    impl From<TypedVal> for f32;
110    impl From<TypedVal> for f64;
111    #[cfg(feature = "simd")]
112    impl From<TypedVal> for V128;
113}
114
115macro_rules! impl_from_typed_value_as_for {
116    ( $( $( #[$attr:meta] )* impl From<TypedVal> for $ty:ty as $as:ty );* $(;)? ) => {
117        $(
118            $( #[$attr] )*
119            impl From<TypedVal> for $ty {
120                fn from(typed_value: TypedVal) -> Self {
121                    <$as as From<TypedVal>>::from(typed_value) as $ty
122                }
123            }
124        )*
125    };
126}
127impl_from_typed_value_as_for! {
128    impl From<TypedVal> for i8 as i32;
129    impl From<TypedVal> for i16 as i32;
130    impl From<TypedVal> for u8 as u32;
131    impl From<TypedVal> for u16 as u32;
132}