Skip to content

Commit

Permalink
Merge #1908
Browse files Browse the repository at this point in the history
1908: Implement TryFrom<Value<T>> for i32/u32/i64/u64/f32/f64 r=syrusakbary a=webmaster128

# Description

After the migration from 0.17 to 1.0 users have to handle much more dynamic return values. This PR makes working with `Value<T>` more convenient by implementing `TryFrom<Value<T>>` for `i32`/`u32`/`i64`/`u64`/`f32`/`f64`.

This PR is tested and demonstrated at CosmWasm/cosmwasm#658

# Review

- [ ] Add a short description of the the change to the CHANGELOG.md file


Co-authored-by: Simon Warta <[email protected]>
  • Loading branch information
bors[bot] and webmaster128 authored Dec 10, 2020
2 parents 39d6959 + 878da59 commit df3a211
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<Value<T>>` for `i32`/`u32`/`i64`/`u64`/`f32`/`f64`

### Changed

Expand Down
6 changes: 3 additions & 3 deletions lib/wasmer-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
}
}
Expand Down
144 changes: 144 additions & 0 deletions lib/wasmer-types/src/values.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -223,6 +224,59 @@ impl<T> From<ExternRef> for Value<T> {
// }
// }

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<T> TryFrom<Value<T>> for i32 {
type Error = &'static str;

fn try_from(value: Value<T>) -> Result<Self, Self::Error> {
value.i32().ok_or(NOT_I32)
}
}

impl<T> TryFrom<Value<T>> for u32 {
type Error = &'static str;

fn try_from(value: Value<T>) -> Result<Self, Self::Error> {
value.i32().ok_or(NOT_I32).map(|int| int as Self)
}
}

impl<T> TryFrom<Value<T>> for i64 {
type Error = &'static str;

fn try_from(value: Value<T>) -> Result<Self, Self::Error> {
value.i64().ok_or(NOT_I64)
}
}

impl<T> TryFrom<Value<T>> for u64 {
type Error = &'static str;

fn try_from(value: Value<T>) -> Result<Self, Self::Error> {
value.i64().ok_or(NOT_I64).map(|int| int as Self)
}
}

impl<T> TryFrom<Value<T>> for f32 {
type Error = &'static str;

fn try_from(value: Value<T>) -> Result<Self, Self::Error> {
value.f32().ok_or(NOT_F32)
}
}

impl<T> TryFrom<Value<T>> for f64 {
type Error = &'static str;

fn try_from(value: Value<T>) -> Result<Self, Self::Error> {
value.f64().ok_or(NOT_F64)
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -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");
}
}

0 comments on commit df3a211

Please sign in to comment.