soroban_wasmi/
value.rs

1use crate::{
2    core::{UntypedVal, ValType, F32, F64},
3    ExternRef,
4    Func,
5    FuncRef,
6};
7
8/// Untyped instances that allow to be typed.
9pub trait WithType {
10    /// The typed output type.
11    type Output;
12
13    /// Converts `self` to [`Self::Output`] using `ty`.
14    fn with_type(self, ty: ValType) -> Self::Output;
15}
16
17impl WithType for UntypedVal {
18    type Output = Val;
19
20    fn with_type(self, ty: ValType) -> Self::Output {
21        match ty {
22            ValType::I32 => Val::I32(self.into()),
23            ValType::I64 => Val::I64(self.into()),
24            ValType::F32 => Val::F32(self.into()),
25            ValType::F64 => Val::F64(self.into()),
26            ValType::FuncRef => Val::FuncRef(self.into()),
27            ValType::ExternRef => Val::ExternRef(self.into()),
28        }
29    }
30}
31
32impl From<Val> for UntypedVal {
33    fn from(value: Val) -> Self {
34        match value {
35            Val::I32(value) => value.into(),
36            Val::I64(value) => value.into(),
37            Val::F32(value) => value.into(),
38            Val::F64(value) => value.into(),
39            Val::FuncRef(value) => value.into(),
40            Val::ExternRef(value) => value.into(),
41        }
42    }
43}
44
45/// Runtime representation of a Wasm value.
46///
47/// Wasm code manipulate values of the four basic value types:
48/// integers and floating-point (IEEE 754-2008) data of 32 or 64 bit width each, respectively.
49///
50/// There is no distinction between signed and unsigned integer types. Instead, integers are
51/// interpreted by respective operations as either unsigned or signed in two’s complement representation.
52#[derive(Clone, Debug)]
53pub enum Val {
54    /// Value of 32-bit signed or unsigned integer.
55    I32(i32),
56    /// Value of 64-bit signed or unsigned integer.
57    I64(i64),
58    /// Value of 32-bit IEEE 754-2008 floating point number.
59    F32(F32),
60    /// Value of 64-bit IEEE 754-2008 floating point number.
61    F64(F64),
62    /// A nullable [`Func`][`crate::Func`] reference, a.k.a. [`FuncRef`].
63    FuncRef(FuncRef),
64    /// A nullable external object reference, a.k.a. [`ExternRef`].
65    ExternRef(ExternRef),
66}
67
68impl Val {
69    /// Creates new default value of given type.
70    #[inline]
71    pub fn default(value_type: ValType) -> Self {
72        match value_type {
73            ValType::I32 => Self::I32(0),
74            ValType::I64 => Self::I64(0),
75            ValType::F32 => Self::F32(0f32.into()),
76            ValType::F64 => Self::F64(0f64.into()),
77            ValType::FuncRef => Self::from(FuncRef::null()),
78            ValType::ExternRef => Self::from(ExternRef::null()),
79        }
80    }
81
82    /// Get variable type for this value.
83    #[inline]
84    pub fn ty(&self) -> ValType {
85        match *self {
86            Self::I32(_) => ValType::I32,
87            Self::I64(_) => ValType::I64,
88            Self::F32(_) => ValType::F32,
89            Self::F64(_) => ValType::F64,
90            Self::FuncRef(_) => ValType::FuncRef,
91            Self::ExternRef(_) => ValType::ExternRef,
92        }
93    }
94
95    /// Returns the underlying `i32` if the type matches otherwise returns `None`.
96    pub fn i32(&self) -> Option<i32> {
97        match self {
98            Self::I32(value) => Some(*value),
99            _ => None,
100        }
101    }
102
103    /// Returns the underlying `i64` if the type matches otherwise returns `None`.
104    pub fn i64(&self) -> Option<i64> {
105        match self {
106            Self::I64(value) => Some(*value),
107            _ => None,
108        }
109    }
110
111    /// Returns the underlying `f32` if the type matches otherwise returns `None`.
112    pub fn f32(&self) -> Option<F32> {
113        match self {
114            Self::F32(value) => Some(*value),
115            _ => None,
116        }
117    }
118
119    /// Returns the underlying `f64` if the type matches otherwise returns `None`.
120    pub fn f64(&self) -> Option<F64> {
121        match self {
122            Self::F64(value) => Some(*value),
123            _ => None,
124        }
125    }
126
127    /// Returns the underlying `funcref` if the type matches otherwise returns `None`.
128    pub fn funcref(&self) -> Option<&FuncRef> {
129        match self {
130            Self::FuncRef(value) => Some(value),
131            _ => None,
132        }
133    }
134
135    /// Returns the underlying `externref` if the type matches otherwise returns `None`.
136    pub fn externref(&self) -> Option<&ExternRef> {
137        match self {
138            Self::ExternRef(value) => Some(value),
139            _ => None,
140        }
141    }
142}
143
144impl From<i32> for Val {
145    #[inline]
146    fn from(val: i32) -> Self {
147        Self::I32(val)
148    }
149}
150
151impl From<i64> for Val {
152    #[inline]
153    fn from(val: i64) -> Self {
154        Self::I64(val)
155    }
156}
157
158impl From<F32> for Val {
159    #[inline]
160    fn from(val: F32) -> Self {
161        Self::F32(val)
162    }
163}
164
165impl From<F64> for Val {
166    #[inline]
167    fn from(val: F64) -> Self {
168        Self::F64(val)
169    }
170}
171
172impl From<FuncRef> for Val {
173    #[inline]
174    fn from(funcref: FuncRef) -> Self {
175        Self::FuncRef(funcref)
176    }
177}
178
179impl From<Func> for Val {
180    #[inline]
181    fn from(func: Func) -> Self {
182        Self::FuncRef(FuncRef::new(func))
183    }
184}
185
186impl From<ExternRef> for Val {
187    #[inline]
188    fn from(externref: ExternRef) -> Self {
189        Self::ExternRef(externref)
190    }
191}