wasmi/
value.rs

1use crate::{
2    core::{TypedVal, UntypedVal},
3    ExternRef,
4    Func,
5    Ref,
6    ValType,
7    F32,
8    F64,
9    V128,
10};
11
12/// Untyped instances that allow to be typed.
13pub trait WithType {
14    /// The typed output type.
15    type Output;
16
17    /// Converts `self` to [`Self::Output`] using `ty`.
18    fn with_type(self, ty: ValType) -> Self::Output;
19}
20
21impl WithType for UntypedVal {
22    type Output = Val;
23
24    fn with_type(self, ty: ValType) -> Self::Output {
25        match ty {
26            ValType::I32 => Val::I32(self.into()),
27            ValType::I64 => Val::I64(self.into()),
28            ValType::F32 => Val::F32(self.into()),
29            ValType::F64 => Val::F64(self.into()),
30            #[cfg(feature = "simd")]
31            ValType::V128 => Val::V128(self.into()),
32            ValType::FuncRef => Val::FuncRef(self.into()),
33            ValType::ExternRef => Val::ExternRef(self.into()),
34            #[cfg(not(feature = "simd"))]
35            unsupported => unimplemented!("encountered unsupported `ValType`: {unsupported:?}"),
36        }
37    }
38}
39
40impl From<Val> for UntypedVal {
41    fn from(value: Val) -> Self {
42        match value {
43            Val::I32(value) => value.into(),
44            Val::I64(value) => value.into(),
45            Val::F32(value) => value.into(),
46            Val::F64(value) => value.into(),
47            #[cfg(feature = "simd")]
48            Val::V128(value) => value.into(),
49            Val::FuncRef(value) => value.into(),
50            Val::ExternRef(value) => value.into(),
51            #[cfg(not(feature = "simd"))]
52            unsupported => unimplemented!("encountered unsupported `Val`: {unsupported:?}"),
53        }
54    }
55}
56
57/// Runtime representation of a Wasm value.
58///
59/// Wasm code manipulate values of the four basic value types:
60/// integers and floating-point (IEEE 754-2008) data of 32 or 64 bit width each, respectively.
61///
62/// There is no distinction between signed and unsigned integer types. Instead, integers are
63/// interpreted by respective operations as either unsigned or signed in two’s complement representation.
64#[derive(Clone, Debug)]
65pub enum Val {
66    /// Value of 32-bit signed or unsigned integer.
67    I32(i32),
68    /// Value of 64-bit signed or unsigned integer.
69    I64(i64),
70    /// Value of 32-bit IEEE 754-2008 floating point number.
71    F32(F32),
72    /// Value of 64-bit IEEE 754-2008 floating point number.
73    F64(F64),
74    /// 128-bit Wasm `simd` proposal vector.
75    V128(V128),
76    /// A nullable [`Func`] reference.
77    FuncRef(Ref<Func>),
78    /// A nullable [`ExternRef`] reference.
79    ExternRef(Ref<ExternRef>),
80}
81
82impl Val {
83    /// Creates new default value of given type.
84    #[inline]
85    pub fn default(value_type: ValType) -> Self {
86        match value_type {
87            ValType::I32 => Self::I32(0),
88            ValType::I64 => Self::I64(0),
89            ValType::F32 => Self::F32(0f32.into()),
90            ValType::F64 => Self::F64(0f64.into()),
91            ValType::V128 => Self::V128(V128::from(0_u128)),
92            ValType::FuncRef => Self::from(<Ref<Func>>::Null),
93            ValType::ExternRef => Self::from(<Ref<ExternRef>>::Null),
94        }
95    }
96
97    /// Get variable type for this value.
98    #[inline]
99    pub fn ty(&self) -> ValType {
100        match *self {
101            Self::I32(_) => ValType::I32,
102            Self::I64(_) => ValType::I64,
103            Self::F32(_) => ValType::F32,
104            Self::F64(_) => ValType::F64,
105            Self::V128(_) => ValType::V128,
106            Self::FuncRef(_) => ValType::FuncRef,
107            Self::ExternRef(_) => ValType::ExternRef,
108        }
109    }
110
111    /// Returns the underlying `i32` if the type matches otherwise returns `None`.
112    pub fn i32(&self) -> Option<i32> {
113        match self {
114            Self::I32(value) => Some(*value),
115            _ => None,
116        }
117    }
118
119    /// Returns the underlying `i64` if the type matches otherwise returns `None`.
120    pub fn i64(&self) -> Option<i64> {
121        match self {
122            Self::I64(value) => Some(*value),
123            _ => None,
124        }
125    }
126
127    /// Returns the underlying `f32` if the type matches otherwise returns `None`.
128    pub fn f32(&self) -> Option<F32> {
129        match self {
130            Self::F32(value) => Some(*value),
131            _ => None,
132        }
133    }
134
135    /// Returns the underlying `f64` if the type matches otherwise returns `None`.
136    pub fn f64(&self) -> Option<F64> {
137        match self {
138            Self::F64(value) => Some(*value),
139            _ => None,
140        }
141    }
142
143    /// Returns the underlying `funcref` if the type matches otherwise returns `None`.
144    pub fn funcref(&self) -> Option<Ref<&Func>> {
145        match self {
146            Self::FuncRef(value) => Some(value.as_ref()),
147            _ => None,
148        }
149    }
150
151    /// Returns the underlying `externref` if the type matches otherwise returns `None`.
152    pub fn externref(&self) -> Option<Ref<&ExternRef>> {
153        match self {
154            Self::ExternRef(value) => Some(value.as_ref()),
155            _ => None,
156        }
157    }
158}
159
160impl From<i32> for Val {
161    #[inline]
162    fn from(val: i32) -> Self {
163        Self::I32(val)
164    }
165}
166
167impl From<i64> for Val {
168    #[inline]
169    fn from(val: i64) -> Self {
170        Self::I64(val)
171    }
172}
173
174impl From<F32> for Val {
175    #[inline]
176    fn from(val: F32) -> Self {
177        Self::F32(val)
178    }
179}
180
181impl From<F64> for Val {
182    #[inline]
183    fn from(val: F64) -> Self {
184        Self::F64(val)
185    }
186}
187
188impl From<Func> for Val {
189    #[inline]
190    fn from(func: Func) -> Self {
191        Self::FuncRef(Ref::Val(func))
192    }
193}
194
195impl From<ExternRef> for Val {
196    #[inline]
197    fn from(externref: ExternRef) -> Self {
198        Self::ExternRef(Ref::Val(externref))
199    }
200}
201
202impl From<Ref<Func>> for Val {
203    #[inline]
204    fn from(funcref: Ref<Func>) -> Self {
205        Self::FuncRef(funcref)
206    }
207}
208
209impl From<Ref<ExternRef>> for Val {
210    #[inline]
211    fn from(externref: Ref<ExternRef>) -> Self {
212        Self::ExternRef(externref)
213    }
214}
215
216impl From<V128> for Val {
217    #[inline]
218    fn from(value: V128) -> Self {
219        Self::V128(value)
220    }
221}
222
223impl From<TypedVal> for Val {
224    fn from(value: TypedVal) -> Self {
225        let untyped = value.untyped();
226        match value.ty() {
227            ValType::I32 => Self::I32(untyped.into()),
228            ValType::I64 => Self::I64(untyped.into()),
229            ValType::F32 => Self::F32(untyped.into()),
230            ValType::F64 => Self::F64(untyped.into()),
231            ValType::V128 => {
232                #[cfg(feature = "simd")]
233                {
234                    Self::V128(untyped.into())
235                }
236                #[cfg(not(feature = "simd"))]
237                {
238                    panic!("`simd` crate feature is disabled")
239                }
240            }
241            ValType::FuncRef => Self::FuncRef(untyped.into()),
242            ValType::ExternRef => Self::ExternRef(untyped.into()),
243        }
244    }
245}
246
247impl From<Val> for TypedVal {
248    fn from(value: Val) -> Self {
249        Self::new(value.ty(), value.into())
250    }
251}