Skip to content

Commit

Permalink
rust: add TypedExecutionResult which allows returning TypedValues
Browse files Browse the repository at this point in the history
  • Loading branch information
axic committed Feb 3, 2021
1 parent c58323a commit 557785f
Showing 1 changed file with 116 additions and 7 deletions.
123 changes: 116 additions & 7 deletions bindings/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,36 @@ impl ExecutionResult {
}
}

/// The result of an execution.
pub struct TypedExecutionResult {
result: sys::FizzyExecutionResult,
value_type: sys::FizzyValueType,
}

impl TypedExecutionResult {
/// True if execution has resulted in a trap.
pub fn trapped(&self) -> bool {
self.result.trapped
}

/// The optional return value. Only a single return value is allowed in WebAssembly 1.0.
pub fn value(&self) -> Option<TypedValue> {
if self.result.has_value {
assert!(!self.result.trapped);
assert!(self.value_type != sys::FizzyValueTypeVoid);
Some(match self.value_type {
sys::FizzyValueTypeI32 => TypedValue::U32(unsafe { self.result.value.i32 }),
sys::FizzyValueTypeI64 => TypedValue::U64(unsafe { self.result.value.i64 }),
sys::FizzyValueTypeF32 => TypedValue::F32(unsafe { self.result.value.f32 }),
sys::FizzyValueTypeF64 => TypedValue::F64(unsafe { self.result.value.f64 }),
_ => panic!(),
})
} else {
None
}
}
}

impl Instance {
/// Get a read-only pointer to the module.
unsafe fn get_module(&self) -> *const sys::FizzyModule {
Expand Down Expand Up @@ -275,7 +305,7 @@ impl Instance {
name: &str,
args: &[TypedValue],
depth: i32,
) -> Result<ExecutionResult, ()> {
) -> Result<TypedExecutionResult, ()> {
let func_idx = self.find_exported_function_index(&name);
if func_idx.is_none() {
return Err(());
Expand Down Expand Up @@ -304,11 +334,10 @@ impl Instance {
let args: Vec<Value> = args.iter().map(|v| v.into()).collect();

let ret = unsafe { self.unsafe_execute(func_idx, &args, depth) };
if !ret.trapped() {
// Validate presence of output whether return type is void or not.
assert!((func_type.output == sys::FizzyValueTypeVoid) == !ret.value().is_some());
}
Ok(ret)
Ok(TypedExecutionResult {
result: ret.0,
value_type: func_type.output,
})
}
}

Expand Down Expand Up @@ -378,6 +407,86 @@ mod tests {
assert_eq!(v.as_f64().unwrap(), f64::MAX);
}

#[test]
fn typed_execution_result() {
let r_fail = sys::FizzyExecutionResult {
trapped: true,
has_value: false,
value: sys::FizzyValue { i32: 0 },
};
let r_success_void = sys::FizzyExecutionResult {
trapped: false,
has_value: false,
value: sys::FizzyValue { i32: 0 },
};
let r_success_u32 = sys::FizzyExecutionResult {
trapped: false,
has_value: true,
value: sys::FizzyValue { i32: u32::MAX },
};
let r_success_u64 = sys::FizzyExecutionResult {
trapped: false,
has_value: true,
value: sys::FizzyValue { i64: u64::MAX },
};
let r_success_f32 = sys::FizzyExecutionResult {
trapped: false,
has_value: true,
value: sys::FizzyValue { f32: f32::MAX },
};
let r_success_f64 = sys::FizzyExecutionResult {
trapped: false,
has_value: true,
value: sys::FizzyValue { f64: f64::MAX },
};

let r = TypedExecutionResult {
result: r_fail,
value_type: sys::FizzyValueTypeVoid,
};
assert!(r.trapped());
assert!(r.value().is_none());

let r = TypedExecutionResult {
result: r_success_void,
value_type: sys::FizzyValueTypeVoid,
};
assert!(!r.trapped());
assert!(r.value().is_none());

let r = TypedExecutionResult {
result: r_success_u32,
value_type: sys::FizzyValueTypeI32,
};
assert!(!r.trapped());
assert!(r.value().is_some());
assert_eq!(r.value().unwrap().as_u32().unwrap(), u32::MAX);

let r = TypedExecutionResult {
result: r_success_u64,
value_type: sys::FizzyValueTypeI64,
};
assert!(!r.trapped());
assert!(r.value().is_some());
assert_eq!(r.value().unwrap().as_u64().unwrap(), u64::MAX);

let r = TypedExecutionResult {
result: r_success_f32,
value_type: sys::FizzyValueTypeF32,
};
assert!(!r.trapped());
assert!(r.value().is_some());
assert_eq!(r.value().unwrap().as_f32().unwrap(), f32::MAX);

let r = TypedExecutionResult {
result: r_success_f64,
value_type: sys::FizzyValueTypeF64,
};
assert!(!r.trapped());
assert!(r.value().is_some());
assert_eq!(r.value().unwrap().as_f64().unwrap(), f64::MAX);
}

#[test]
fn validate_wasm() {
// Empty
Expand Down Expand Up @@ -523,7 +632,7 @@ mod tests {
let result = result.unwrap();
assert!(!result.trapped());
assert!(result.value().is_some());
assert_eq!(result.value().unwrap().as_i32(), 42);
assert_eq!(result.value().unwrap().as_u32().unwrap(), 42);

// Non-function export.
let result = instance.execute("g1", &[], 0);
Expand Down

0 comments on commit 557785f

Please sign in to comment.