Add UnexpectedSignature error and remove Value err
This commit is contained in:
parent
30bc275a7a
commit
c5e28d0a8e
12
src/host.rs
12
src/host.rs
|
@ -1,6 +1,6 @@
|
|||
use std::any::TypeId;
|
||||
use value::{RuntimeValue, TryInto};
|
||||
use {Error, Trap};
|
||||
use Trap;
|
||||
|
||||
/// Safe wrapper for list of arguments.
|
||||
#[derive(Debug)]
|
||||
|
@ -18,8 +18,8 @@ impl<'a> RuntimeArgs<'a> {
|
|||
/// # Errors
|
||||
///
|
||||
/// Returns `Err` if cast is invalid or not enough arguments.
|
||||
pub fn nth_checked<T>(&self, idx: usize) -> Result<T, Error> where RuntimeValue: TryInto<T, Error> {
|
||||
Ok(self.nth_value_checked(idx)?.try_into().map_err(|_| Error::Value("Invalid argument cast".to_owned()))?)
|
||||
pub fn nth_checked<T>(&self, idx: usize) -> Result<T, Trap> where RuntimeValue: TryInto<T, ::value::Error> {
|
||||
Ok(self.nth_value_checked(idx)?.try_into().map_err(|_| Trap::UnexpectedSignature)?)
|
||||
}
|
||||
|
||||
/// Extract argument as a [`RuntimeValue`] by index `idx`.
|
||||
|
@ -27,9 +27,9 @@ impl<'a> RuntimeArgs<'a> {
|
|||
/// # Errors
|
||||
///
|
||||
/// Returns `Err` if this list has not enough arguments.
|
||||
pub fn nth_value_checked(&self, idx: usize) -> Result<RuntimeValue, Error> {
|
||||
pub fn nth_value_checked(&self, idx: usize) -> Result<RuntimeValue, Trap> {
|
||||
if self.0.len() <= idx {
|
||||
return Err(Error::Value("Invalid argument index".to_owned()));
|
||||
return Err(Trap::UnexpectedSignature);
|
||||
}
|
||||
Ok(self.0[idx])
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ impl<'a> RuntimeArgs<'a> {
|
|||
/// # Panics
|
||||
///
|
||||
/// Panics if cast is invalid or not enough arguments.
|
||||
pub fn nth<T>(&self, idx: usize) -> T where RuntimeValue: TryInto<T, Error> {
|
||||
pub fn nth<T>(&self, idx: usize) -> T where RuntimeValue: TryInto<T, ::value::Error> {
|
||||
let value = self.nth_value_checked(idx).expect("Invalid argument index");
|
||||
value.try_into().expect("Unexpected argument type")
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ use std::fmt;
|
|||
use std::error;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Error type which can happen at execution time.
|
||||
/// Error type which can thrown by wasm code or by host environment.
|
||||
///
|
||||
/// Under some conditions, wasm execution may produce a `Trap`, which immediately aborts execution.
|
||||
/// Traps can't be handled by WebAssembly code, but are reported to the embedder.
|
||||
|
@ -169,6 +169,12 @@ pub enum Trap {
|
|||
/// Extensive inlining might also be the cause of stack overflow.
|
||||
StackOverflow,
|
||||
|
||||
/// Unexpected signature provided.
|
||||
///
|
||||
/// This can happen if [`FuncInstance`] was invoked
|
||||
/// with mismatching signature.
|
||||
UnexpectedSignature,
|
||||
|
||||
/// Error specified by the host.
|
||||
///
|
||||
/// Typically returned from an implementation of [`Externals`].
|
||||
|
|
138
src/runner.rs
138
src/runner.rs
|
@ -370,8 +370,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
fn run_if(&mut self, context: &mut FunctionContext, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome, Trap> {
|
||||
let condition: bool = context
|
||||
.value_stack_mut()
|
||||
.pop_as()
|
||||
.expect("Due to validation stack top should be I32");
|
||||
.pop_as();
|
||||
let block_frame_type = if condition { BlockFrameType::IfTrue } else {
|
||||
let else_pos = labels[&context.position];
|
||||
if !labels.contains_key(&else_pos) {
|
||||
|
@ -404,9 +403,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
}
|
||||
|
||||
fn run_br_if(&mut self, context: &mut FunctionContext, label_idx: u32) -> Result<InstructionOutcome, Trap> {
|
||||
let condition = context.value_stack_mut()
|
||||
.pop_as()
|
||||
.expect("Due to validation stack should contain value");
|
||||
let condition = context.value_stack_mut().pop_as();
|
||||
if condition {
|
||||
Ok(InstructionOutcome::Branch(label_idx as usize))
|
||||
} else {
|
||||
|
@ -416,8 +413,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
|
||||
fn run_br_table(&mut self, context: &mut FunctionContext, table: &[u32], default: u32) -> Result<InstructionOutcome, Trap> {
|
||||
let index: u32 = context.value_stack_mut()
|
||||
.pop_as()
|
||||
.expect("Due to validation stack should contain value");
|
||||
.pop_as();
|
||||
Ok(InstructionOutcome::Branch(table.get(index as usize).cloned().unwrap_or(default) as usize))
|
||||
}
|
||||
|
||||
|
@ -444,8 +440,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
) -> Result<InstructionOutcome, Trap> {
|
||||
let table_func_idx: u32 = context
|
||||
.value_stack_mut()
|
||||
.pop_as()
|
||||
.expect("Due to validation stack top should be I32");
|
||||
.pop_as();
|
||||
let table = context
|
||||
.module()
|
||||
.table_by_index(DEFAULT_TABLE_INDEX)
|
||||
|
@ -546,8 +541,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
where RuntimeValue: From<T>, T: LittleEndianConvert {
|
||||
let raw_address = context
|
||||
.value_stack_mut()
|
||||
.pop_as()
|
||||
.expect("Due to vaidation stack should contain value");
|
||||
.pop_as();
|
||||
let address =
|
||||
effective_address(
|
||||
offset,
|
||||
|
@ -568,8 +562,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
where T: ExtendInto<U>, RuntimeValue: From<U>, T: LittleEndianConvert {
|
||||
let raw_address = context
|
||||
.value_stack_mut()
|
||||
.pop_as()
|
||||
.expect("Due to vaidation stack should contain value");
|
||||
.pop_as();
|
||||
let address =
|
||||
effective_address(
|
||||
offset,
|
||||
|
@ -591,16 +584,14 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
}
|
||||
|
||||
fn run_store<T>(&mut self, context: &mut FunctionContext, _align: u32, offset: u32) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: TryInto<T, Error>, T: LittleEndianConvert {
|
||||
where RuntimeValue: TryInto<T, ::value::Error>, T: LittleEndianConvert {
|
||||
let stack_value = context
|
||||
.value_stack_mut()
|
||||
.pop_as::<T>()
|
||||
.expect("Due to vaidation stack should contain value")
|
||||
.into_little_endian();
|
||||
let raw_address = context
|
||||
.value_stack_mut()
|
||||
.pop_as::<u32>()
|
||||
.expect("Due to validation stack should contain value");
|
||||
.pop_as::<u32>();
|
||||
let address =
|
||||
effective_address(
|
||||
offset,
|
||||
|
@ -622,7 +613,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
offset: u32,
|
||||
) -> Result<InstructionOutcome, Trap>
|
||||
where
|
||||
RuntimeValue: TryInto<T, Error>,
|
||||
RuntimeValue: TryInto<T, ::value::Error>,
|
||||
T: WrapInto<U>,
|
||||
U: LittleEndianConvert,
|
||||
{
|
||||
|
@ -634,8 +625,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
let stack_value = stack_value.wrap_into().into_little_endian();
|
||||
let raw_address = context
|
||||
.value_stack_mut()
|
||||
.pop_as::<u32>()
|
||||
.expect("Due to validation stack should contain value");
|
||||
.pop_as::<u32>();
|
||||
let address =
|
||||
effective_address(
|
||||
offset,
|
||||
|
@ -663,8 +653,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
fn run_grow_memory(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap> {
|
||||
let pages: u32 = context
|
||||
.value_stack_mut()
|
||||
.pop_as()
|
||||
.expect("Due to validation stack should contain value");
|
||||
.pop_as();
|
||||
let m = context.module()
|
||||
.memory_by_index(DEFAULT_MEMORY_INDEX)
|
||||
.expect("Due to validation memory should exists");
|
||||
|
@ -687,7 +676,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
|
||||
fn run_relop<T, F>(&mut self, context: &mut FunctionContext, f: F) -> Result<InstructionOutcome, Trap>
|
||||
where
|
||||
RuntimeValue: TryInto<T, Error>,
|
||||
RuntimeValue: TryInto<T, ::value::Error>,
|
||||
F: FnOnce(T, T) -> bool,
|
||||
{
|
||||
let (left, right) = context
|
||||
|
@ -704,78 +693,76 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
}
|
||||
|
||||
fn run_eqz<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> + Default {
|
||||
where RuntimeValue: TryInto<T, ::value::Error>, T: PartialEq<T> + Default {
|
||||
let v = context
|
||||
.value_stack_mut()
|
||||
.pop_as::<T>()
|
||||
.expect("Due to vaidation stack should contain value");
|
||||
.pop_as::<T>();
|
||||
let v = RuntimeValue::I32(if v == Default::default() { 1 } else { 0 });
|
||||
context.value_stack_mut().push(v)?;
|
||||
Ok(InstructionOutcome::RunNextInstruction)
|
||||
}
|
||||
|
||||
fn run_eq<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: TryInto<T, Error>, T: PartialEq<T>
|
||||
where RuntimeValue: TryInto<T, ::value::Error>, T: PartialEq<T>
|
||||
{
|
||||
self.run_relop(context, |left, right| left == right)
|
||||
}
|
||||
|
||||
fn run_ne<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> {
|
||||
where RuntimeValue: TryInto<T, ::value::Error>, T: PartialEq<T> {
|
||||
self.run_relop(context, |left, right| left != right)
|
||||
}
|
||||
|
||||
fn run_lt<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> + Display {
|
||||
where RuntimeValue: TryInto<T, ::value::Error>, T: PartialOrd<T> + Display {
|
||||
self.run_relop(context, |left, right| left < right)
|
||||
}
|
||||
|
||||
fn run_gt<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> {
|
||||
where RuntimeValue: TryInto<T, ::value::Error>, T: PartialOrd<T> {
|
||||
self.run_relop(context, |left, right| left > right)
|
||||
}
|
||||
|
||||
fn run_lte<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> {
|
||||
where RuntimeValue: TryInto<T, ::value::Error>, T: PartialOrd<T> {
|
||||
self.run_relop(context, |left, right| left <= right)
|
||||
}
|
||||
|
||||
fn run_gte<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> {
|
||||
where RuntimeValue: TryInto<T, ::value::Error>, T: PartialOrd<T> {
|
||||
self.run_relop(context, |left, right| left >= right)
|
||||
}
|
||||
|
||||
fn run_unop<T, U, F>(&mut self, context: &mut FunctionContext, f: F) -> Result<InstructionOutcome, Trap>
|
||||
where
|
||||
F: FnOnce(T) -> U,
|
||||
RuntimeValue: From<U> + TryInto<T, Error>
|
||||
RuntimeValue: From<U> + TryInto<T, ::value::Error>
|
||||
{
|
||||
let v = context
|
||||
.value_stack_mut()
|
||||
.pop_as::<T>()
|
||||
.map(|v| f(v))
|
||||
.expect("Due to vaidation stack should contain value");
|
||||
.pop_as::<T>();
|
||||
let v = f(v);
|
||||
context.value_stack_mut().push(v.into())?;
|
||||
Ok(InstructionOutcome::RunNextInstruction)
|
||||
}
|
||||
|
||||
fn run_clz<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: Integer<T> {
|
||||
self.run_unop(context, |v| v.leading_zeros())
|
||||
}
|
||||
|
||||
fn run_ctz<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: Integer<T> {
|
||||
self.run_unop(context, |v| v.trailing_zeros())
|
||||
}
|
||||
|
||||
fn run_popcnt<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: Integer<T> {
|
||||
self.run_unop(context, |v| v.count_ones())
|
||||
}
|
||||
|
||||
fn run_add<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> {
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: ArithmeticOps<T> {
|
||||
let (left, right) = context
|
||||
.value_stack_mut()
|
||||
.pop_pair_as::<T>()
|
||||
|
@ -786,7 +773,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
}
|
||||
|
||||
fn run_sub<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> {
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: ArithmeticOps<T> {
|
||||
let (left, right) = context
|
||||
.value_stack_mut()
|
||||
.pop_pair_as::<T>()
|
||||
|
@ -797,7 +784,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
}
|
||||
|
||||
fn run_mul<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> {
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: ArithmeticOps<T> {
|
||||
let (left, right) = context
|
||||
.value_stack_mut()
|
||||
.pop_pair_as::<T>()
|
||||
|
@ -808,7 +795,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
}
|
||||
|
||||
fn run_div<T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U> + Display, U: ArithmeticOps<U> + TransmuteInto<T> {
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: TransmuteInto<U> + Display, U: ArithmeticOps<U> + TransmuteInto<T> {
|
||||
let (left, right) = context
|
||||
.value_stack_mut()
|
||||
.pop_pair_as::<T>()
|
||||
|
@ -821,7 +808,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
}
|
||||
|
||||
fn run_rem<T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U>, U: Integer<U> + TransmuteInto<T> {
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: TransmuteInto<U>, U: Integer<U> + TransmuteInto<T> {
|
||||
let (left, right) = context
|
||||
.value_stack_mut()
|
||||
.pop_pair_as::<T>()
|
||||
|
@ -834,7 +821,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
}
|
||||
|
||||
fn run_and<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<<T as ops::BitAnd>::Output> + TryInto<T, Error>, T: ops::BitAnd<T> {
|
||||
where RuntimeValue: From<<T as ops::BitAnd>::Output> + TryInto<T, ::value::Error>, T: ops::BitAnd<T> {
|
||||
let (left, right) = context
|
||||
.value_stack_mut()
|
||||
.pop_pair_as::<T>()
|
||||
|
@ -845,7 +832,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
}
|
||||
|
||||
fn run_or<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<<T as ops::BitOr>::Output> + TryInto<T, Error>, T: ops::BitOr<T> {
|
||||
where RuntimeValue: From<<T as ops::BitOr>::Output> + TryInto<T, ::value::Error>, T: ops::BitOr<T> {
|
||||
let (left, right) = context
|
||||
.value_stack_mut()
|
||||
.pop_pair_as::<T>()
|
||||
|
@ -856,7 +843,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
}
|
||||
|
||||
fn run_xor<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<<T as ops::BitXor>::Output> + TryInto<T, Error>, T: ops::BitXor<T> {
|
||||
where RuntimeValue: From<<T as ops::BitXor>::Output> + TryInto<T, ::value::Error>, T: ops::BitXor<T> {
|
||||
let (left, right) = context
|
||||
.value_stack_mut()
|
||||
.pop_pair_as::<T>()
|
||||
|
@ -867,7 +854,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
}
|
||||
|
||||
fn run_shl<T>(&mut self, context: &mut FunctionContext, mask: T) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<<T as ops::Shl<T>>::Output> + TryInto<T, Error>, T: ops::Shl<T> + ops::BitAnd<T, Output=T> {
|
||||
where RuntimeValue: From<<T as ops::Shl<T>>::Output> + TryInto<T, ::value::Error>, T: ops::Shl<T> + ops::BitAnd<T, Output=T> {
|
||||
let (left, right) = context
|
||||
.value_stack_mut()
|
||||
.pop_pair_as::<T>()
|
||||
|
@ -878,7 +865,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
}
|
||||
|
||||
fn run_shr<T, U>(&mut self, context: &mut FunctionContext, mask: U) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U>, U: ops::Shr<U> + ops::BitAnd<U, Output=U>, <U as ops::Shr<U>>::Output: TransmuteInto<T> {
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: TransmuteInto<U>, U: ops::Shr<U> + ops::BitAnd<U, Output=U>, <U as ops::Shr<U>>::Output: TransmuteInto<T> {
|
||||
let (left, right) = context
|
||||
.value_stack_mut()
|
||||
.pop_pair_as::<T>()
|
||||
|
@ -891,7 +878,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
}
|
||||
|
||||
fn run_rotl<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: Integer<T> {
|
||||
let (left, right) = context
|
||||
.value_stack_mut()
|
||||
.pop_pair_as::<T>()
|
||||
|
@ -902,7 +889,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
}
|
||||
|
||||
fn run_rotr<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T>
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: Integer<T>
|
||||
{
|
||||
let (left, right) = context
|
||||
.value_stack_mut()
|
||||
|
@ -914,51 +901,51 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
}
|
||||
|
||||
fn run_abs<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T>
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: Float<T>
|
||||
{
|
||||
self.run_unop(context, |v| v.abs())
|
||||
}
|
||||
|
||||
fn run_neg<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where
|
||||
RuntimeValue: From<<T as ops::Neg>::Output> + TryInto<T, Error>,
|
||||
RuntimeValue: From<<T as ops::Neg>::Output> + TryInto<T, ::value::Error>,
|
||||
T: ops::Neg
|
||||
{
|
||||
self.run_unop(context, |v| v.neg())
|
||||
}
|
||||
|
||||
fn run_ceil<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T>
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: Float<T>
|
||||
{
|
||||
self.run_unop(context, |v| v.ceil())
|
||||
}
|
||||
|
||||
fn run_floor<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T>
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: Float<T>
|
||||
{
|
||||
self.run_unop(context, |v| v.floor())
|
||||
}
|
||||
|
||||
fn run_trunc<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T>
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: Float<T>
|
||||
{
|
||||
self.run_unop(context, |v| v.trunc())
|
||||
}
|
||||
|
||||
fn run_nearest<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T>
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: Float<T>
|
||||
{
|
||||
self.run_unop(context, |v| v.nearest())
|
||||
}
|
||||
|
||||
fn run_sqrt<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T>
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: Float<T>
|
||||
{
|
||||
self.run_unop(context, |v| v.sqrt())
|
||||
}
|
||||
|
||||
fn run_min<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T>
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: Float<T>
|
||||
{
|
||||
let (left, right) = context
|
||||
.value_stack_mut()
|
||||
|
@ -970,7 +957,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
}
|
||||
|
||||
fn run_max<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: Float<T> {
|
||||
let (left, right) = context
|
||||
.value_stack_mut()
|
||||
.pop_pair_as::<T>()
|
||||
|
@ -981,7 +968,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
}
|
||||
|
||||
fn run_copysign<T>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
|
||||
where RuntimeValue: From<T> + TryInto<T, ::value::Error>, T: Float<T> {
|
||||
let (left, right) = context
|
||||
.value_stack_mut()
|
||||
.pop_pair_as::<T>()
|
||||
|
@ -992,16 +979,15 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
}
|
||||
|
||||
fn run_wrap<T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<U> + TryInto<T, Error>, T: WrapInto<U> {
|
||||
where RuntimeValue: From<U> + TryInto<T, ::value::Error>, T: WrapInto<U> {
|
||||
self.run_unop(context, |v| v.wrap_into())
|
||||
}
|
||||
|
||||
fn run_trunc_to_int<T, U, V>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where RuntimeValue: From<V> + TryInto<T, Error>, T: TryTruncateInto<U, Trap>, U: TransmuteInto<V>, {
|
||||
where RuntimeValue: From<V> + TryInto<T, ::value::Error>, T: TryTruncateInto<U, Trap>, U: TransmuteInto<V>, {
|
||||
let v = context
|
||||
.value_stack_mut()
|
||||
.pop_as::<T>()
|
||||
.expect("Due to vaidation stack should contain value");
|
||||
.pop_as::<T>();
|
||||
|
||||
v.try_truncate_into()
|
||||
.map(|v| v.transmute_into())
|
||||
|
@ -1011,12 +997,11 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
|
||||
fn run_extend<T, U, V>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where
|
||||
RuntimeValue: From<V> + TryInto<T, Error>, T: ExtendInto<U>, U: TransmuteInto<V>
|
||||
RuntimeValue: From<V> + TryInto<T, ::value::Error>, T: ExtendInto<U>, U: TransmuteInto<V>
|
||||
{
|
||||
let v = context
|
||||
.value_stack_mut()
|
||||
.pop_as::<T>()
|
||||
.expect("Due to vaidation stack should contain value");
|
||||
.pop_as::<T>();
|
||||
|
||||
let v = v.extend_into().transmute_into();
|
||||
context.value_stack_mut().push(v.into())?;
|
||||
|
@ -1026,12 +1011,11 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
|
||||
fn run_reinterpret<T, U>(&mut self, context: &mut FunctionContext) -> Result<InstructionOutcome, Trap>
|
||||
where
|
||||
RuntimeValue: From<U>, RuntimeValue: TryInto<T, Error>, T: TransmuteInto<U>
|
||||
RuntimeValue: From<U>, RuntimeValue: TryInto<T, ::value::Error>, T: TransmuteInto<U>
|
||||
{
|
||||
let v = context
|
||||
.value_stack_mut()
|
||||
.pop_as::<T>()
|
||||
.expect("Due to vaidation stack should contain value");
|
||||
.pop_as::<T>();
|
||||
|
||||
let v = v.transmute_into();
|
||||
context.value_stack_mut().push(v.into())?;
|
||||
|
@ -1263,22 +1247,22 @@ impl ValueStack {
|
|||
}
|
||||
}
|
||||
|
||||
fn pop_as<T>(&mut self) -> Result<T, Error>
|
||||
fn pop_as<T>(&mut self) -> T
|
||||
where
|
||||
RuntimeValue: TryInto<T, Error>,
|
||||
RuntimeValue: TryInto<T, ::value::Error>,
|
||||
{
|
||||
let value = self.stack_with_limit
|
||||
.pop()
|
||||
.expect("Due to validation stack shouldn't be empty");
|
||||
TryInto::try_into(value)
|
||||
TryInto::try_into(value).expect("Due to validation stack top's type should match")
|
||||
}
|
||||
|
||||
fn pop_pair_as<T>(&mut self) -> Result<(T, T), Error>
|
||||
where
|
||||
RuntimeValue: TryInto<T, Error>,
|
||||
RuntimeValue: TryInto<T, ::value::Error>,
|
||||
{
|
||||
let right = self.pop_as()?;
|
||||
let left = self.pop_as()?;
|
||||
let right = self.pop_as();
|
||||
let left = self.pop_as();
|
||||
Ok((left, right))
|
||||
}
|
||||
|
||||
|
|
41
src/value.rs
41
src/value.rs
|
@ -1,9 +1,16 @@
|
|||
use std::{i32, i64, u32, u64, f32};
|
||||
use std::io;
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use {Error, Trap};
|
||||
use {Trap};
|
||||
use parity_wasm::elements::ValueType;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
UnexpectedType {
|
||||
expected: ValueType,
|
||||
},
|
||||
InvalidLittleEndianBuffer,
|
||||
}
|
||||
|
||||
/// Runtime value.
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
|
@ -180,7 +187,7 @@ impl TryInto<bool, Error> for RuntimeValue {
|
|||
fn try_into(self) -> Result<bool, Error> {
|
||||
match self {
|
||||
RuntimeValue::I32(val) => Ok(val != 0),
|
||||
_ => Err(Error::Value("32-bit int value expected".to_owned())),
|
||||
_ => Err(Error::UnexpectedType { expected: ValueType::I32 }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -189,7 +196,7 @@ impl TryInto<i32, Error> for RuntimeValue {
|
|||
fn try_into(self) -> Result<i32, Error> {
|
||||
match self {
|
||||
RuntimeValue::I32(val) => Ok(val),
|
||||
_ => Err(Error::Value("32-bit int value expected".to_owned())),
|
||||
_ => Err(Error::UnexpectedType { expected: ValueType::I32 }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -198,7 +205,7 @@ impl TryInto<i64, Error> for RuntimeValue {
|
|||
fn try_into(self) -> Result<i64, Error> {
|
||||
match self {
|
||||
RuntimeValue::I64(val) => Ok(val),
|
||||
_ => Err(Error::Value("64-bit int value expected".to_owned())),
|
||||
_ => Err(Error::UnexpectedType { expected: ValueType::I64 }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +214,7 @@ impl TryInto<f32, Error> for RuntimeValue {
|
|||
fn try_into(self) -> Result<f32, Error> {
|
||||
match self {
|
||||
RuntimeValue::F32(val) => Ok(val),
|
||||
_ => Err(Error::Value("32-bit float value expected".to_owned())),
|
||||
_ => Err(Error::UnexpectedType { expected: ValueType::F32 }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -216,7 +223,7 @@ impl TryInto<f64, Error> for RuntimeValue {
|
|||
fn try_into(self) -> Result<f64, Error> {
|
||||
match self {
|
||||
RuntimeValue::F64(val) => Ok(val),
|
||||
_ => Err(Error::Value("64-bit float value expected".to_owned())),
|
||||
_ => Err(Error::UnexpectedType { expected: ValueType::F64 }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -225,7 +232,7 @@ impl TryInto<u32, Error> for RuntimeValue {
|
|||
fn try_into(self) -> Result<u32, Error> {
|
||||
match self {
|
||||
RuntimeValue::I32(val) => Ok(val as u32),
|
||||
_ => Err(Error::Value("32-bit int value expected".to_owned())),
|
||||
_ => Err(Error::UnexpectedType { expected: ValueType::I32 }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -234,7 +241,7 @@ impl TryInto<u64, Error> for RuntimeValue {
|
|||
fn try_into(self) -> Result<u64, Error> {
|
||||
match self {
|
||||
RuntimeValue::I64(val) => Ok(val as u64),
|
||||
_ => Err(Error::Value("64-bit int value expected".to_owned())),
|
||||
_ => Err(Error::UnexpectedType { expected: ValueType::I64 }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -379,7 +386,7 @@ impl LittleEndianConvert for i8 {
|
|||
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> {
|
||||
buffer.get(0)
|
||||
.map(|v| *v as i8)
|
||||
.ok_or_else(|| Error::Value("invalid little endian buffer".into()))
|
||||
.ok_or_else(|| Error::InvalidLittleEndianBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -391,7 +398,7 @@ impl LittleEndianConvert for u8 {
|
|||
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> {
|
||||
buffer.get(0)
|
||||
.cloned()
|
||||
.ok_or_else(|| Error::Value("invalid little endian buffer".into()))
|
||||
.ok_or_else(|| Error::InvalidLittleEndianBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,7 +412,7 @@ impl LittleEndianConvert for i16 {
|
|||
|
||||
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> {
|
||||
io::Cursor::new(buffer).read_i16::<LittleEndian>()
|
||||
.map_err(|e| Error::Value(e.to_string()))
|
||||
.map_err(|_| Error::InvalidLittleEndianBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -419,7 +426,7 @@ impl LittleEndianConvert for u16 {
|
|||
|
||||
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> {
|
||||
io::Cursor::new(buffer).read_u16::<LittleEndian>()
|
||||
.map_err(|e| Error::Value(e.to_string()))
|
||||
.map_err(|_| Error::InvalidLittleEndianBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -433,7 +440,7 @@ impl LittleEndianConvert for i32 {
|
|||
|
||||
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> {
|
||||
io::Cursor::new(buffer).read_i32::<LittleEndian>()
|
||||
.map_err(|e| Error::Value(e.to_string()))
|
||||
.map_err(|_| Error::InvalidLittleEndianBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -447,7 +454,7 @@ impl LittleEndianConvert for u32 {
|
|||
|
||||
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> {
|
||||
io::Cursor::new(buffer).read_u32::<LittleEndian>()
|
||||
.map_err(|e| Error::Value(e.to_string()))
|
||||
.map_err(|_| Error::InvalidLittleEndianBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -461,7 +468,7 @@ impl LittleEndianConvert for i64 {
|
|||
|
||||
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> {
|
||||
io::Cursor::new(buffer).read_i64::<LittleEndian>()
|
||||
.map_err(|e| Error::Value(e.to_string()))
|
||||
.map_err(|_| Error::InvalidLittleEndianBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -476,7 +483,7 @@ impl LittleEndianConvert for f32 {
|
|||
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> {
|
||||
io::Cursor::new(buffer).read_u32::<LittleEndian>()
|
||||
.map(f32_from_bits)
|
||||
.map_err(|e| Error::Value(e.to_string()))
|
||||
.map_err(|_| Error::InvalidLittleEndianBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -491,7 +498,7 @@ impl LittleEndianConvert for f64 {
|
|||
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> {
|
||||
io::Cursor::new(buffer).read_u64::<LittleEndian>()
|
||||
.map(f64_from_bits)
|
||||
.map_err(|e| Error::Value(e.to_string()))
|
||||
.map_err(|_| Error::InvalidLittleEndianBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue