1use crate::store::AsStoreRef;
2use crate::vm::{VMExternRef, VMFuncRef};
3use crate::ExternRef;
4use crate::Function;
5use std::convert::TryFrom;
6use std::fmt;
7use wasmer_types::Type;
8
9pub use wasmer_types::RawValue;
10
11#[derive(Clone)]
18pub enum Value {
19 I32(i32),
23
24 I64(i64),
28
29 F32(f32),
31
32 F64(f64),
34
35 ExternRef(Option<ExternRef>),
37
38 FuncRef(Option<Function>),
40
41 V128(u128),
43}
44
45macro_rules! accessors {
46 ($bind:ident $(($variant:ident($ty:ty) $get:ident $unwrap:ident $cvt:expr))*) => ($(
47 pub fn $get(&self) -> Option<$ty> {
50 if let Self::$variant($bind) = self {
51 Some($cvt)
52 } else {
53 None
54 }
55 }
56
57 pub fn $unwrap(&self) -> $ty {
64 self.$get().expect(concat!("expected ", stringify!($ty)))
65 }
66 )*)
67}
68
69impl Value {
70 pub fn null() -> Self {
72 Self::ExternRef(None)
73 }
74
75 pub fn ty(&self) -> Type {
77 match self {
78 Self::I32(_) => Type::I32,
79 Self::I64(_) => Type::I64,
80 Self::F32(_) => Type::F32,
81 Self::F64(_) => Type::F64,
82 Self::ExternRef(_) => Type::ExternRef,
83 Self::FuncRef(_) => Type::FuncRef,
84 Self::V128(_) => Type::V128,
85 }
86 }
87
88 pub fn as_raw(&self, store: &impl AsStoreRef) -> RawValue {
90 match *self {
91 Self::I32(i32) => RawValue { i32 },
92 Self::I64(i64) => RawValue { i64 },
93 Self::F32(f32) => RawValue { f32 },
94 Self::F64(f64) => RawValue { f64 },
95 Self::V128(u128) => RawValue { u128 },
96 Self::FuncRef(Some(ref f)) => f.vm_funcref(store).into_raw(),
97
98 Self::FuncRef(None) => RawValue { funcref: 0 },
99 Self::ExternRef(Some(ref e)) => e.vm_externref().into_raw(),
100 Self::ExternRef(None) => RawValue { externref: 0 },
101 }
102 }
103
104 pub unsafe fn from_raw(store: &mut impl crate::AsStoreMut, ty: Type, raw: RawValue) -> Self {
109 match ty {
110 Type::I32 => Self::I32(raw.i32),
111 Type::I64 => Self::I64(raw.i64),
112 Type::F32 => Self::F32(raw.f32),
113 Type::F64 => Self::F64(raw.f64),
114 Type::V128 => Self::V128(raw.u128),
115 Type::FuncRef => {
116 Self::FuncRef(VMFuncRef::from_raw(raw).map(|f| Function::from_vm_funcref(store, f)))
117 }
118 Type::ExternRef => Self::ExternRef(
119 VMExternRef::from_raw(raw).map(|e| ExternRef::from_vm_externref(store, e)),
120 ),
121 }
122 }
123
124 pub fn is_from_store(&self, store: &impl AsStoreRef) -> bool {
132 match self {
133 Self::I32(_)
134 | Self::I64(_)
135 | Self::F32(_)
136 | Self::F64(_)
137 | Self::V128(_)
138 | Self::ExternRef(None)
139 | Self::FuncRef(None) => true,
140 Self::ExternRef(Some(e)) => e.is_from_store(store),
141 Self::FuncRef(Some(f)) => f.is_from_store(store),
142 }
143 }
144
145 accessors! {
146 e
147 (I32(i32) i32 unwrap_i32 *e)
148 (I64(i64) i64 unwrap_i64 *e)
149 (F32(f32) f32 unwrap_f32 *e)
150 (F64(f64) f64 unwrap_f64 *e)
151 (ExternRef(&Option<ExternRef>) externref unwrap_externref e)
152 (FuncRef(&Option<Function>) funcref unwrap_funcref e)
153 (V128(u128) v128 unwrap_v128 *e)
154 }
155}
156
157impl fmt::Debug for Value {
158 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159 match self {
160 Self::I32(v) => write!(f, "I32({:?})", v),
161 Self::I64(v) => write!(f, "I64({:?})", v),
162 Self::F32(v) => write!(f, "F32({:?})", v),
163 Self::F64(v) => write!(f, "F64({:?})", v),
164 Self::ExternRef(None) => write!(f, "Null ExternRef"),
165 Self::ExternRef(Some(v)) => write!(f, "ExternRef({:?})", v),
166 Self::FuncRef(None) => write!(f, "Null FuncRef"),
167 Self::FuncRef(Some(v)) => write!(f, "FuncRef({:?})", v),
168 Self::V128(v) => write!(f, "V128({:?})", v),
169 }
170 }
171}
172
173impl fmt::Display for Value {
174 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
175 write!(
176 f,
177 "{}",
178 match self {
179 Self::I32(v) => v.to_string(),
180 Self::I64(v) => v.to_string(),
181 Self::F32(v) => v.to_string(),
182 Self::F64(v) => v.to_string(),
183 Self::ExternRef(_) => "externref".to_string(),
184 Self::FuncRef(_) => "funcref".to_string(),
185 Self::V128(v) => v.to_string(),
186 }
187 )
188 }
189}
190
191impl PartialEq for Value {
192 fn eq(&self, o: &Self) -> bool {
193 match (self, o) {
194 (Self::I32(a), Self::I32(b)) => a == b,
195 (Self::I64(a), Self::I64(b)) => a == b,
196 (Self::F32(a), Self::F32(b)) => a == b,
197 (Self::F64(a), Self::F64(b)) => a == b,
198 (Self::V128(a), Self::V128(b)) => a == b,
199 _ => false,
200 }
201 }
202}
203
204impl From<i32> for Value {
205 fn from(val: i32) -> Self {
206 Self::I32(val)
207 }
208}
209
210impl From<u32> for Value {
211 fn from(val: u32) -> Self {
212 Self::I32(val as i32)
214 }
215}
216
217impl From<i64> for Value {
218 fn from(val: i64) -> Self {
219 Self::I64(val)
220 }
221}
222
223impl From<u64> for Value {
224 fn from(val: u64) -> Self {
225 Self::I64(val as i64)
227 }
228}
229
230impl From<f32> for Value {
231 fn from(val: f32) -> Self {
232 Self::F32(val)
233 }
234}
235
236impl From<f64> for Value {
237 fn from(val: f64) -> Self {
238 Self::F64(val)
239 }
240}
241
242impl From<Function> for Value {
243 fn from(val: Function) -> Self {
244 Self::FuncRef(Some(val))
245 }
246}
247
248impl From<Option<Function>> for Value {
249 fn from(val: Option<Function>) -> Self {
250 Self::FuncRef(val)
251 }
252}
253
254impl From<ExternRef> for Value {
255 fn from(val: ExternRef) -> Self {
256 Self::ExternRef(Some(val))
257 }
258}
259
260impl From<Option<ExternRef>> for Value {
261 fn from(val: Option<ExternRef>) -> Self {
262 Self::ExternRef(val)
263 }
264}
265
266const NOT_I32: &str = "Value is not of Wasm type i32";
267const NOT_I64: &str = "Value is not of Wasm type i64";
268const NOT_F32: &str = "Value is not of Wasm type f32";
269const NOT_F64: &str = "Value is not of Wasm type f64";
270const NOT_FUNCREF: &str = "Value is not of Wasm type funcref";
271const NOT_EXTERNREF: &str = "Value is not of Wasm type externref";
272
273impl TryFrom<Value> for i32 {
274 type Error = &'static str;
275
276 fn try_from(value: Value) -> Result<Self, Self::Error> {
277 value.i32().ok_or(NOT_I32)
278 }
279}
280
281impl TryFrom<Value> for u32 {
282 type Error = &'static str;
283
284 fn try_from(value: Value) -> Result<Self, Self::Error> {
285 value.i32().ok_or(NOT_I32).map(|int| int as Self)
286 }
287}
288
289impl TryFrom<Value> for i64 {
290 type Error = &'static str;
291
292 fn try_from(value: Value) -> Result<Self, Self::Error> {
293 value.i64().ok_or(NOT_I64)
294 }
295}
296
297impl TryFrom<Value> for u64 {
298 type Error = &'static str;
299
300 fn try_from(value: Value) -> Result<Self, Self::Error> {
301 value.i64().ok_or(NOT_I64).map(|int| int as Self)
302 }
303}
304
305impl TryFrom<Value> for f32 {
306 type Error = &'static str;
307
308 fn try_from(value: Value) -> Result<Self, Self::Error> {
309 value.f32().ok_or(NOT_F32)
310 }
311}
312
313impl TryFrom<Value> for f64 {
314 type Error = &'static str;
315
316 fn try_from(value: Value) -> Result<Self, Self::Error> {
317 value.f64().ok_or(NOT_F64)
318 }
319}
320
321impl TryFrom<Value> for Option<Function> {
322 type Error = &'static str;
323
324 fn try_from(value: Value) -> Result<Self, Self::Error> {
325 match value {
326 Value::FuncRef(f) => Ok(f),
327 _ => Err(NOT_FUNCREF),
328 }
329 }
330}
331
332impl TryFrom<Value> for Option<ExternRef> {
333 type Error = &'static str;
334
335 fn try_from(value: Value) -> Result<Self, Self::Error> {
336 match value {
337 Value::ExternRef(e) => Ok(e),
338 _ => Err(NOT_EXTERNREF),
339 }
340 }
341}
342
343#[cfg(test)]
344mod tests {
345 use super::*;
346
347 #[test]
348 fn test_value_i32_from_u32() {
349 let bytes = [0x00, 0x00, 0x00, 0x00];
350 let v = Value::from(u32::from_be_bytes(bytes));
351 assert_eq!(v, Value::I32(i32::from_be_bytes(bytes)));
352
353 let bytes = [0x00, 0x00, 0x00, 0x01];
354 let v = Value::from(u32::from_be_bytes(bytes));
355 assert_eq!(v, Value::I32(i32::from_be_bytes(bytes)));
356
357 let bytes = [0xAA, 0xBB, 0xCC, 0xDD];
358 let v = Value::from(u32::from_be_bytes(bytes));
359 assert_eq!(v, Value::I32(i32::from_be_bytes(bytes)));
360
361 let bytes = [0xFF, 0xFF, 0xFF, 0xFF];
362 let v = Value::from(u32::from_be_bytes(bytes));
363 assert_eq!(v, Value::I32(i32::from_be_bytes(bytes)));
364 }
365
366 #[test]
367 fn test_value_i64_from_u64() {
368 let bytes = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
369 let v = Value::from(u64::from_be_bytes(bytes));
370 assert_eq!(v, Value::I64(i64::from_be_bytes(bytes)));
371
372 let bytes = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01];
373 let v = Value::from(u64::from_be_bytes(bytes));
374 assert_eq!(v, Value::I64(i64::from_be_bytes(bytes)));
375
376 let bytes = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11];
377 let v = Value::from(u64::from_be_bytes(bytes));
378 assert_eq!(v, Value::I64(i64::from_be_bytes(bytes)));
379
380 let bytes = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
381 let v = Value::from(u64::from_be_bytes(bytes));
382 assert_eq!(v, Value::I64(i64::from_be_bytes(bytes)));
383 }
384
385 #[test]
386 fn convert_value_to_i32() {
387 let value = Value::I32(5678);
388 let result = i32::try_from(value);
389 assert_eq!(result.unwrap(), 5678);
390
391 let value = Value::from(u32::MAX);
392 let result = i32::try_from(value);
393 assert_eq!(result.unwrap(), -1);
394
395 let value = Value::V128(42);
396 let result = i32::try_from(value);
397 assert_eq!(result.unwrap_err(), "Value is not of Wasm type i32");
398 }
399
400 #[test]
401 fn convert_value_to_u32() {
402 let value = Value::from(u32::MAX);
403 let result = u32::try_from(value);
404 assert_eq!(result.unwrap(), u32::MAX);
405
406 let value = Value::I32(-1);
407 let result = u32::try_from(value);
408 assert_eq!(result.unwrap(), u32::MAX);
409
410 let value = Value::V128(42);
411 let result = u32::try_from(value);
412 assert_eq!(result.unwrap_err(), "Value is not of Wasm type i32");
413 }
414
415 #[test]
416 fn convert_value_to_i64() {
417 let value = Value::I64(5678);
418 let result = i64::try_from(value);
419 assert_eq!(result.unwrap(), 5678);
420
421 let value = Value::from(u64::MAX);
422 let result = i64::try_from(value);
423 assert_eq!(result.unwrap(), -1);
424
425 let value = Value::V128(42);
426 let result = i64::try_from(value);
427 assert_eq!(result.unwrap_err(), "Value is not of Wasm type i64");
428 }
429
430 #[test]
431 fn convert_value_to_u64() {
432 let value = Value::from(u64::MAX);
433 let result = u64::try_from(value);
434 assert_eq!(result.unwrap(), u64::MAX);
435
436 let value = Value::I64(-1);
437 let result = u64::try_from(value);
438 assert_eq!(result.unwrap(), u64::MAX);
439
440 let value = Value::V128(42);
441 let result = u64::try_from(value);
442 assert_eq!(result.unwrap_err(), "Value is not of Wasm type i64");
443 }
444
445 #[test]
446 fn convert_value_to_f32() {
447 let value = Value::F32(1.234);
448 let result = f32::try_from(value);
449 assert_eq!(result.unwrap(), 1.234);
450
451 let value = Value::V128(42);
452 let result = f32::try_from(value);
453 assert_eq!(result.unwrap_err(), "Value is not of Wasm type f32");
454
455 let value = Value::F64(1.234);
456 let result = f32::try_from(value);
457 assert_eq!(result.unwrap_err(), "Value is not of Wasm type f32");
458 }
459
460 #[test]
461 fn convert_value_to_f64() {
462 let value = Value::F64(1.234);
463 let result = f64::try_from(value);
464 assert_eq!(result.unwrap(), 1.234);
465
466 let value = Value::V128(42);
467 let result = f64::try_from(value);
468 assert_eq!(result.unwrap_err(), "Value is not of Wasm type f64");
469
470 let value = Value::F32(1.234);
471 let result = f64::try_from(value);
472 assert_eq!(result.unwrap_err(), "Value is not of Wasm type f64");
473 }
474}