diff --git a/CHANGELOG.md b/CHANGELOG.md index 0781539e053..f8c5cc0b61d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * [#1867](https://github.com/wasmerio/wasmer/pull/1867) Added `Metering::get_remaining_points` and `Metering::set_remaining_points` * [#1881](https://github.com/wasmerio/wasmer/pull/1881) Added `UnsupportedTarget` error to `CompileError` +* [#1908](https://github.com/wasmerio/wasmer/pull/1908) Implemented `TryFrom>` for `i32`/`u32`/`i64`/`u64`/`f32`/`f64` ### Changed diff --git a/lib/wasmer-types/src/lib.rs b/lib/wasmer-types/src/lib.rs index 3004ea503dc..8e158f1bf6d 100644 --- a/lib/wasmer-types/src/lib.rs +++ b/lib/wasmer-types/src/lib.rs @@ -38,14 +38,14 @@ mod lib { #[cfg(feature = "core")] pub mod std { pub use alloc::{borrow, boxed, format, rc, slice, string, vec}; - pub use core::{any, cell, fmt, hash, marker, ops, ptr, sync}; + pub use core::{any, cell, convert, fmt, hash, marker, ops, ptr, sync}; } #[cfg(feature = "std")] pub mod std { pub use std::{ - any, borrow, boxed, cell, fmt, format, hash, marker, ops, ptr, rc, slice, string, sync, - vec, + any, borrow, boxed, cell, convert, fmt, format, hash, marker, ops, ptr, rc, slice, + string, sync, vec, }; } } diff --git a/lib/wasmer-types/src/values.rs b/lib/wasmer-types/src/values.rs index bf497701b1a..bf5600ccffd 100644 --- a/lib/wasmer-types/src/values.rs +++ b/lib/wasmer-types/src/values.rs @@ -1,3 +1,4 @@ +use crate::lib::std::convert::TryFrom; use crate::lib::std::fmt; use crate::lib::std::ptr; use crate::lib::std::string::{String, ToString}; @@ -223,6 +224,59 @@ impl From for Value { // } // } +const NOT_I32: &'static str = "Value is not of Wasm type i32"; +const NOT_I64: &'static str = "Value is not of Wasm type i64"; +const NOT_F32: &'static str = "Value is not of Wasm type f32"; +const NOT_F64: &'static str = "Value is not of Wasm type f64"; + +impl TryFrom> for i32 { + type Error = &'static str; + + fn try_from(value: Value) -> Result { + value.i32().ok_or(NOT_I32) + } +} + +impl TryFrom> for u32 { + type Error = &'static str; + + fn try_from(value: Value) -> Result { + value.i32().ok_or(NOT_I32).map(|int| int as Self) + } +} + +impl TryFrom> for i64 { + type Error = &'static str; + + fn try_from(value: Value) -> Result { + value.i64().ok_or(NOT_I64) + } +} + +impl TryFrom> for u64 { + type Error = &'static str; + + fn try_from(value: Value) -> Result { + value.i64().ok_or(NOT_I64).map(|int| int as Self) + } +} + +impl TryFrom> for f32 { + type Error = &'static str; + + fn try_from(value: Value) -> Result { + value.f32().ok_or(NOT_F32) + } +} + +impl TryFrom> for f64 { + type Error = &'static str; + + fn try_from(value: Value) -> Result { + value.f64().ok_or(NOT_F64) + } +} + #[cfg(test)] mod tests { use super::*; @@ -264,4 +318,94 @@ mod tests { let v = Value::<()>::from(u64::from_be_bytes(bytes.clone())); assert_eq!(v, Value::I64(i64::from_be_bytes(bytes.clone()))); } + + #[test] + fn convert_value_to_i32() { + let value = Value::<()>::I32(5678); + let result = i32::try_from(value); + assert_eq!(result.unwrap(), 5678); + + let value = Value::<()>::from(u32::MAX); + let result = i32::try_from(value); + assert_eq!(result.unwrap(), -1); + + let value = Value::<()>::V128(42); + let result = i32::try_from(value); + assert_eq!(result.unwrap_err(), "Value is not of Wasm type i32"); + } + + #[test] + fn convert_value_to_u32() { + let value = Value::<()>::from(u32::MAX); + let result = u32::try_from(value); + assert_eq!(result.unwrap(), u32::MAX); + + let value = Value::<()>::I32(-1); + let result = u32::try_from(value); + assert_eq!(result.unwrap(), u32::MAX); + + let value = Value::<()>::V128(42); + let result = u32::try_from(value); + assert_eq!(result.unwrap_err(), "Value is not of Wasm type i32"); + } + + #[test] + fn convert_value_to_i64() { + let value = Value::<()>::I64(5678); + let result = i64::try_from(value); + assert_eq!(result.unwrap(), 5678); + + let value = Value::<()>::from(u64::MAX); + let result = i64::try_from(value); + assert_eq!(result.unwrap(), -1); + + let value = Value::<()>::V128(42); + let result = i64::try_from(value); + assert_eq!(result.unwrap_err(), "Value is not of Wasm type i64"); + } + + #[test] + fn convert_value_to_u64() { + let value = Value::<()>::from(u64::MAX); + let result = u64::try_from(value); + assert_eq!(result.unwrap(), u64::MAX); + + let value = Value::<()>::I64(-1); + let result = u64::try_from(value); + assert_eq!(result.unwrap(), u64::MAX); + + let value = Value::<()>::V128(42); + let result = u64::try_from(value); + assert_eq!(result.unwrap_err(), "Value is not of Wasm type i64"); + } + + #[test] + fn convert_value_to_f32() { + let value = Value::<()>::F32(1.234); + let result = f32::try_from(value); + assert_eq!(result.unwrap(), 1.234); + + let value = Value::<()>::V128(42); + let result = f32::try_from(value); + assert_eq!(result.unwrap_err(), "Value is not of Wasm type f32"); + + let value = Value::<()>::F64(1.234); + let result = f32::try_from(value); + assert_eq!(result.unwrap_err(), "Value is not of Wasm type f32"); + } + + #[test] + fn convert_value_to_f64() { + let value = Value::<()>::F64(1.234); + let result = f64::try_from(value); + assert_eq!(result.unwrap(), 1.234); + + let value = Value::<()>::V128(42); + let result = f64::try_from(value); + assert_eq!(result.unwrap_err(), "Value is not of Wasm type f64"); + + let value = Value::<()>::F32(1.234); + let result = f64::try_from(value); + assert_eq!(result.unwrap_err(), "Value is not of Wasm type f64"); + } }