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