From c877d64508109dc4467c5783184e5baa9ad1341e Mon Sep 17 00:00:00 2001 From: Jef Date: Wed, 31 Oct 2018 16:01:20 +0100 Subject: [PATCH] Remove tag from RuntimeValue (#133) * Remove tag from runtime value * Add explanation of `RuntimeValueInternal`, move it so I don't need to do `pub(crate)` --- src/runner.rs | 806 +++++++++++++++++++++++++++++++------------------- src/value.rs | 176 +++++++---- 2 files changed, 612 insertions(+), 370 deletions(-) diff --git a/src/runner.rs b/src/runner.rs index 7e171c3..64c464d 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -1,24 +1,22 @@ #[allow(unused_imports)] use alloc::prelude::*; +use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX}; +use core::fmt; use core::ops; use core::{u32, usize}; -use core::fmt; -use core::iter::repeat; -use parity_wasm::elements::Local; -use {Trap, TrapKind, Signature}; -use module::ModuleRef; -use memory::MemoryRef; -use func::{FuncRef, FuncInstance, FuncInstanceInternal}; -use value::{ - RuntimeValue, FromRuntimeValue, WrapInto, TryTruncateInto, ExtendInto, - ArithmeticOps, Integer, Float, LittleEndianConvert, TransmuteInto, -}; +use func::{FuncInstance, FuncInstanceInternal, FuncRef}; use host::Externals; -use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX}; -use types::ValueType; -use memory_units::Pages; -use nan_preserving_float::{F32, F64}; use isa; +use memory::MemoryRef; +use memory_units::Pages; +use module::ModuleRef; +use nan_preserving_float::{F32, F64}; +use parity_wasm::elements::Local; +use value::{ + ArithmeticOps, ExtendInto, Float, Integer, LittleEndianConvert, RuntimeValue, TransmuteInto, + TryTruncateInto, WrapInto, +}; +use {Signature, Trap, TrapKind, ValueType}; /// Maximum number of entries in value stack. pub const DEFAULT_VALUE_STACK_LIMIT: usize = (1024 * 1024) / ::core::mem::size_of::(); @@ -26,6 +24,104 @@ pub const DEFAULT_VALUE_STACK_LIMIT: usize = (1024 * 1024) / ::core::mem::size_o // TODO: Make these parameters changeble. pub const DEFAULT_CALL_STACK_LIMIT: usize = 64 * 1024; +/// This is a wrapper around u64 to allow us to treat runtime values as a tag-free `u64` +/// (where if the runtime value is <64 bits the upper bits are 0). This is safe, since +/// all of the possible runtime values are valid to create from 64 defined bits, so if +/// types don't line up we get a logic error (which will ideally be caught by the wasm +/// spec tests) and not undefined behaviour. +/// +/// At the boundary between the interpreter and the outside world we convert to the public +/// `RuntimeValue` type, which can then be matched on. We can create a `RuntimeValue` from +/// a `RuntimeValueInternal` only when the type is statically known, which it always is +/// at these boundaries. +#[derive(Copy, Clone, Debug, PartialEq, Default)] +#[repr(transparent)] +struct RuntimeValueInternal(pub u64); + +impl RuntimeValueInternal { + pub fn with_type(self, ty: ValueType) -> RuntimeValue { + match ty { + ValueType::I32 => RuntimeValue::I32(<_>::from_runtime_value_internal(self)), + ValueType::I64 => RuntimeValue::I64(<_>::from_runtime_value_internal(self)), + ValueType::F32 => RuntimeValue::F32(<_>::from_runtime_value_internal(self)), + ValueType::F64 => RuntimeValue::F64(<_>::from_runtime_value_internal(self)), + } + } +} + +trait FromRuntimeValueInternal +where + Self: Sized, +{ + fn from_runtime_value_internal(val: RuntimeValueInternal) -> Self; +} + +macro_rules! impl_from_runtime_value_internal { + ($($t:ty),*) => { + $( + impl FromRuntimeValueInternal for $t { + fn from_runtime_value_internal( + RuntimeValueInternal(val): RuntimeValueInternal, + ) -> Self { + val as _ + } + } + + impl From<$t> for RuntimeValueInternal { + fn from(other: $t) -> Self { + RuntimeValueInternal(other as _) + } + } + )* + }; +} + +macro_rules! impl_from_runtime_value_internal_float { + ($($t:ty),*) => { + $( + impl FromRuntimeValueInternal for $t { + fn from_runtime_value_internal( + RuntimeValueInternal(val): RuntimeValueInternal, + ) -> Self { + <$t>::from_bits(val as _) + } + } + + impl From<$t> for RuntimeValueInternal { + fn from(other: $t) -> Self { + RuntimeValueInternal(other.to_bits() as _) + } + } + )* + }; +} + +impl_from_runtime_value_internal!(i8, u8, i16, u16, i32, u32, i64, u64); +impl_from_runtime_value_internal_float!(f32, f64, F32, F64); + +impl From for RuntimeValueInternal { + fn from(other: bool) -> Self { + (if other { 1 } else { 0 }).into() + } +} + +impl FromRuntimeValueInternal for bool { + fn from_runtime_value_internal(RuntimeValueInternal(val): RuntimeValueInternal) -> Self { + val != 0 + } +} + +impl From for RuntimeValueInternal { + fn from(other: RuntimeValue) -> Self { + match other { + RuntimeValue::I32(val) => val.into(), + RuntimeValue::I64(val) => val.into(), + RuntimeValue::F32(val) => val.into(), + RuntimeValue::F64(val) => val.into(), + } + } +} + /// Interpreter action to execute after executing instruction. pub enum InstructionOutcome { /// Continue with next instruction. @@ -78,14 +174,13 @@ pub struct Interpreter { impl Interpreter { pub fn new(func: &FuncRef, args: &[RuntimeValue]) -> Result { let mut value_stack = ValueStack::with_limit(DEFAULT_VALUE_STACK_LIMIT); - for arg in args { - value_stack - .push(*arg) - .map_err( - // There is not enough space for pushing initial arguments. - // Weird, but bail out anyway. - |_| Trap::from(TrapKind::StackOverflow) - )?; + for &arg in args { + let arg = arg.into(); + value_stack.push(arg).map_err( + // There is not enough space for pushing initial arguments. + // Weird, but bail out anyway. + |_| Trap::from(TrapKind::StackOverflow), + )?; } let mut call_stack = Vec::new(); @@ -106,16 +201,19 @@ impl Interpreter { &self.state } - pub fn start_execution<'a, E: Externals + 'a>(&mut self, externals: &'a mut E) -> Result, Trap> { + pub fn start_execution<'a, E: Externals + 'a>( + &mut self, + externals: &'a mut E, + ) -> Result, Trap> { // Ensure that the VM has not been executed. This is checked in `FuncInvocation::start_execution`. assert!(self.state == InterpreterState::Initialized); self.state = InterpreterState::Started; self.run_interpreter_loop(externals)?; - let opt_return_value = self.return_type.map(|_vt| { - self.value_stack.pop() - }); + let opt_return_value = self + .return_type + .map(|vt| self.value_stack.pop().with_type(vt)); // Ensure that stack is empty after the execution. This is guaranteed by the validation properties. assert!(self.value_stack.len() == 0); @@ -123,7 +221,11 @@ impl Interpreter { Ok(opt_return_value) } - pub fn resume_execution<'a, E: Externals + 'a>(&mut self, return_val: Option, externals: &'a mut E) -> Result, Trap> { + pub fn resume_execution<'a, E: Externals + 'a>( + &mut self, + return_val: Option, + externals: &'a mut E, + ) -> Result, Trap> { use core::mem::swap; // Ensure that the VM is resumable. This is checked in `FuncInvocation::resume_execution`. @@ -131,25 +233,18 @@ impl Interpreter { let mut resumable_state = InterpreterState::Started; swap(&mut self.state, &mut resumable_state); - let expected_ty = match resumable_state { - InterpreterState::Resumable(ty) => ty, - _ => unreachable!("Resumable arm is checked above is_resumable; qed"), - }; - - let value_ty = return_val.as_ref().map(|val| val.value_type()); - if value_ty != expected_ty { - return Err(TrapKind::UnexpectedSignature.into()); - } if let Some(return_val) = return_val { - self.value_stack.push(return_val).map_err(Trap::new)?; + self.value_stack + .push(return_val.into()) + .map_err(Trap::new)?; } self.run_interpreter_loop(externals)?; - let opt_return_value = self.return_type.map(|_vt| { - self.value_stack.pop() - }); + let opt_return_value = self + .return_type + .map(|vt| self.value_stack.pop().with_type(vt)); // Ensure that stack is empty after the execution. This is guaranteed by the validation properties. assert!(self.value_stack.len() == 0); @@ -157,11 +252,14 @@ impl Interpreter { Ok(opt_return_value) } - fn run_interpreter_loop<'a, E: Externals + 'a>(&mut self, externals: &'a mut E) -> Result<(), Trap> { + fn run_interpreter_loop<'a, E: Externals + 'a>( + &mut self, + externals: &'a mut E, + ) -> Result<(), Trap> { loop { - let mut function_context = self.call_stack - .pop() - .expect("on loop entry - not empty; on loop continue - checking for emptiness; qed"); + let mut function_context = self.call_stack.pop().expect( + "on loop entry - not empty; on loop continue - checking for emptiness; qed", + ); let function_ref = function_context.function.clone(); let function_body = function_ref .body() @@ -174,11 +272,9 @@ impl Interpreter { function_context.initialize(&function_body.locals, &mut self.value_stack)?; } - let function_return = - self.do_run_function( - &mut function_context, - &function_body.code, - ).map_err(Trap::new)?; + let function_return = self + .do_run_function(&mut function_context, &function_body.code) + .map_err(Trap::new)?; match function_return { RunResult::Return => { @@ -187,7 +283,7 @@ impl Interpreter { // are done executing. return Ok(()); } - }, + } RunResult::NestedCall(nested_func) => { if self.call_stack.len() + 1 >= DEFAULT_CALL_STACK_LIMIT { return Err(TrapKind::StackOverflow.into()); @@ -198,21 +294,24 @@ impl Interpreter { let nested_context = FunctionContext::new(nested_func.clone()); self.call_stack.push(function_context); self.call_stack.push(nested_context); - }, + } FuncInstanceInternal::Host { ref signature, .. } => { let args = prepare_function_args(signature, &mut self.value_stack); // We push the function context first. If the VM is not resumable, it does no harm. If it is, we then save the context here. self.call_stack.push(function_context); - let return_val = match FuncInstance::invoke(&nested_func, &args, externals) { - Ok(val) => val, - Err(trap) => { - if trap.kind().is_host() { - self.state = InterpreterState::Resumable(nested_func.signature().return_type()); + let return_val = + match FuncInstance::invoke(&nested_func, &args, externals) { + Ok(val) => val, + Err(trap) => { + if trap.kind().is_host() { + self.state = InterpreterState::Resumable( + nested_func.signature().return_type(), + ); + } + return Err(trap); } - return Err(trap); - }, - }; + }; // Check if `return_val` matches the signature. let value_ty = return_val.as_ref().map(|val| val.value_type()); @@ -222,36 +321,40 @@ impl Interpreter { } if let Some(return_val) = return_val { - self.value_stack.push(return_val).map_err(Trap::new)?; + self.value_stack + .push(return_val.into()) + .map_err(Trap::new)?; } } } - }, + } } } } - fn do_run_function(&mut self, function_context: &mut FunctionContext, instructions: &isa::Instructions) - -> Result - { + fn do_run_function( + &mut self, + function_context: &mut FunctionContext, + instructions: &isa::Instructions, + ) -> Result { let mut iter = instructions.iterate_from(function_context.position); loop { let instruction = iter.next().expect("instruction"); match self.run_instruction(function_context, instruction)? { - InstructionOutcome::RunNextInstruction => {}, + InstructionOutcome::RunNextInstruction => {} InstructionOutcome::Branch(target) => { iter = instructions.iterate_from(target.dst_pc); self.value_stack.drop_keep(target.drop_keep); - }, + } InstructionOutcome::ExecuteCall(func_ref) => { function_context.position = iter.position(); return Ok(RunResult::NestedCall(func_ref)); - }, + } InstructionOutcome::Return(drop_keep) => { self.value_stack.drop_keep(drop_keep); break; - }, + } } } @@ -259,7 +362,11 @@ impl Interpreter { } #[inline(always)] - fn run_instruction(&mut self, context: &mut FunctionContext, instruction: &isa::Instruction) -> Result { + fn run_instruction( + &mut self, + context: &mut FunctionContext, + instruction: &isa::Instruction, + ) -> Result { match instruction { &isa::Instruction::Unreachable => self.run_unreachable(context), @@ -285,34 +392,60 @@ impl Interpreter { &isa::Instruction::I64Load(offset) => self.run_load::(context, offset), &isa::Instruction::F32Load(offset) => self.run_load::(context, offset), &isa::Instruction::F64Load(offset) => self.run_load::(context, offset), - &isa::Instruction::I32Load8S(offset) => self.run_load_extend::(context, offset), - &isa::Instruction::I32Load8U(offset) => self.run_load_extend::(context, offset), - &isa::Instruction::I32Load16S(offset) => self.run_load_extend::(context, offset), - &isa::Instruction::I32Load16U(offset) => self.run_load_extend::(context, offset), - &isa::Instruction::I64Load8S(offset) => self.run_load_extend::(context, offset), - &isa::Instruction::I64Load8U(offset) => self.run_load_extend::(context, offset), - &isa::Instruction::I64Load16S(offset) => self.run_load_extend::(context, offset), - &isa::Instruction::I64Load16U(offset) => self.run_load_extend::(context, offset), - &isa::Instruction::I64Load32S(offset) => self.run_load_extend::(context, offset), - &isa::Instruction::I64Load32U(offset) => self.run_load_extend::(context, offset), + &isa::Instruction::I32Load8S(offset) => { + self.run_load_extend::(context, offset) + } + &isa::Instruction::I32Load8U(offset) => { + self.run_load_extend::(context, offset) + } + &isa::Instruction::I32Load16S(offset) => { + self.run_load_extend::(context, offset) + } + &isa::Instruction::I32Load16U(offset) => { + self.run_load_extend::(context, offset) + } + &isa::Instruction::I64Load8S(offset) => { + self.run_load_extend::(context, offset) + } + &isa::Instruction::I64Load8U(offset) => { + self.run_load_extend::(context, offset) + } + &isa::Instruction::I64Load16S(offset) => { + self.run_load_extend::(context, offset) + } + &isa::Instruction::I64Load16U(offset) => { + self.run_load_extend::(context, offset) + } + &isa::Instruction::I64Load32S(offset) => { + self.run_load_extend::(context, offset) + } + &isa::Instruction::I64Load32U(offset) => { + self.run_load_extend::(context, offset) + } &isa::Instruction::I32Store(offset) => self.run_store::(context, offset), &isa::Instruction::I64Store(offset) => self.run_store::(context, offset), &isa::Instruction::F32Store(offset) => self.run_store::(context, offset), &isa::Instruction::F64Store(offset) => self.run_store::(context, offset), &isa::Instruction::I32Store8(offset) => self.run_store_wrap::(context, offset), - &isa::Instruction::I32Store16(offset) => self.run_store_wrap::(context, offset), + &isa::Instruction::I32Store16(offset) => { + self.run_store_wrap::(context, offset) + } &isa::Instruction::I64Store8(offset) => self.run_store_wrap::(context, offset), - &isa::Instruction::I64Store16(offset) => self.run_store_wrap::(context, offset), - &isa::Instruction::I64Store32(offset) => self.run_store_wrap::(context, offset), + &isa::Instruction::I64Store16(offset) => { + self.run_store_wrap::(context, offset) + } + &isa::Instruction::I64Store32(offset) => { + self.run_store_wrap::(context, offset) + } &isa::Instruction::CurrentMemory => self.run_current_memory(context), &isa::Instruction::GrowMemory => self.run_grow_memory(context), &isa::Instruction::I32Const(val) => self.run_const(val.into()), &isa::Instruction::I64Const(val) => self.run_const(val.into()), - &isa::Instruction::F32Const(val) => self.run_const(RuntimeValue::decode_f32(val)), - &isa::Instruction::F64Const(val) => self.run_const(RuntimeValue::decode_f64(val)), + &isa::Instruction::F32Const(val) => self.run_const(val.into()), + &isa::Instruction::F64Const(val) => self.run_const(val.into()), &isa::Instruction::I32Eqz => self.run_eqz::(), &isa::Instruction::I32Eq => self.run_eq::(), @@ -449,11 +582,18 @@ impl Interpreter { } } - fn run_unreachable(&mut self, _context: &mut FunctionContext) -> Result { + fn run_unreachable( + &mut self, + _context: &mut FunctionContext, + ) -> Result { Err(TrapKind::Unreachable) } - fn run_br(&mut self, _context: &mut FunctionContext, target: isa::Target) -> Result { + fn run_br( + &mut self, + _context: &mut FunctionContext, + target: isa::Target, + ) -> Result { Ok(InstructionOutcome::Branch(target)) } @@ -471,7 +611,6 @@ impl Interpreter { if condition { Ok(InstructionOutcome::RunNextInstruction) } else { - Ok(InstructionOutcome::Branch(target)) } } @@ -516,7 +655,8 @@ impl Interpreter { .module() .table_by_index(DEFAULT_TABLE_INDEX) .expect("Due to validation table should exists"); - let func_ref = table.get(table_func_idx) + let func_ref = table + .get(table_func_idx) .map_err(|_| TrapKind::TableAccessOutOfBounds)? .ok_or_else(|| TrapKind::ElemUninitialized)?; @@ -541,13 +681,9 @@ impl Interpreter { } fn run_select(&mut self) -> Result { - let (left, mid, right) = self - .value_stack - .pop_triple(); + let (left, mid, right) = self.value_stack.pop_triple(); - let condition = right - .try_into() - .expect("Due to validation stack top should be I32"); + let condition = <_>::from_runtime_value_internal(right); let val = if condition { left } else { mid }; self.value_stack.push(val)?; Ok(InstructionOutcome::RunNextInstruction) @@ -560,18 +696,13 @@ impl Interpreter { } fn run_set_local(&mut self, index: u32) -> Result { - let val = self - .value_stack - .pop(); + let val = self.value_stack.pop(); *self.value_stack.pick_mut(index as usize) = val; Ok(InstructionOutcome::RunNextInstruction) } fn run_tee_local(&mut self, index: u32) -> Result { - let val = self - .value_stack - .top() - .clone(); + let val = self.value_stack.top().clone(); *self.value_stack.pick_mut(index as usize) = val; Ok(InstructionOutcome::RunNextInstruction) } @@ -586,7 +717,7 @@ impl Interpreter { .global_by_index(index) .expect("Due to validation global should exists"); let val = global.get(); - self.value_stack.push(val)?; + self.value_stack.push(val.into())?; Ok(InstructionOutcome::RunNextInstruction) } @@ -595,72 +726,75 @@ impl Interpreter { context: &mut FunctionContext, index: u32, ) -> Result { - let val = self - .value_stack - .pop(); + let val = self.value_stack.pop(); let global = context .module() .global_by_index(index) .expect("Due to validation global should exists"); - global.set(val).expect("Due to validation set to a global should succeed"); + global + .set(val.with_type(global.value_type())) + .expect("Due to validation set to a global should succeed"); Ok(InstructionOutcome::RunNextInstruction) } - fn run_load(&mut self, context: &mut FunctionContext, offset: u32) -> Result - where RuntimeValue: From, T: LittleEndianConvert { - let raw_address = self - .value_stack - .pop_as(); - let address = - effective_address( - offset, - raw_address, - )?; + fn run_load( + &mut self, + context: &mut FunctionContext, + offset: u32, + ) -> Result + where + RuntimeValueInternal: From, + T: LittleEndianConvert, + { + let raw_address = self.value_stack.pop_as(); + let address = effective_address(offset, raw_address)?; let m = context .memory() .expect("Due to validation memory should exists"); - let n: T = m.get_value(address) + let n: T = m + .get_value(address) .map_err(|_| TrapKind::MemoryAccessOutOfBounds)?; self.value_stack.push(n.into())?; Ok(InstructionOutcome::RunNextInstruction) } - fn run_load_extend(&mut self, context: &mut FunctionContext, offset: u32) -> Result - where T: ExtendInto, RuntimeValue: From, T: LittleEndianConvert { - let raw_address = self - .value_stack - .pop_as(); - let address = - effective_address( - offset, - raw_address, - )?; + fn run_load_extend( + &mut self, + context: &mut FunctionContext, + offset: u32, + ) -> Result + where + T: ExtendInto, + RuntimeValueInternal: From, + T: LittleEndianConvert, + { + let raw_address = self.value_stack.pop_as(); + let address = effective_address(offset, raw_address)?; let m = context .memory() .expect("Due to validation memory should exists"); - let v: T = m.get_value(address) + let v: T = m + .get_value(address) .map_err(|_| TrapKind::MemoryAccessOutOfBounds)?; let stack_value: U = v.extend_into(); - self - .value_stack + self.value_stack .push(stack_value.into()) .map_err(Into::into) .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_store(&mut self, context: &mut FunctionContext, offset: u32) -> Result - where T: FromRuntimeValue, T: LittleEndianConvert { - let stack_value = self - .value_stack - .pop_as::(); - let raw_address = self - .value_stack - .pop_as::(); - let address = - effective_address( - offset, - raw_address, - )?; + fn run_store( + &mut self, + context: &mut FunctionContext, + offset: u32, + ) -> Result + where + T: FromRuntimeValueInternal, + T: LittleEndianConvert, + { + let stack_value = self.value_stack.pop_as::(); + let raw_address = self.value_stack.pop_as::(); + let address = effective_address(offset, raw_address)?; let m = context .memory() @@ -676,24 +810,14 @@ impl Interpreter { offset: u32, ) -> Result where - T: FromRuntimeValue, + T: FromRuntimeValueInternal, T: WrapInto, U: LittleEndianConvert, { - let stack_value: T = self - .value_stack - .pop() - .try_into() - .expect("Due to validation value should be of proper type"); + let stack_value: T = <_>::from_runtime_value_internal(self.value_stack.pop()); let stack_value = stack_value.wrap_into(); - let raw_address = self - .value_stack - .pop_as::(); - let address = - effective_address( - offset, - raw_address, - )?; + let raw_address = self.value_stack.pop_as::(); + let address = effective_address(offset, raw_address)?; let m = context .memory() .expect("Due to validation memory should exists"); @@ -702,21 +826,23 @@ impl Interpreter { Ok(InstructionOutcome::RunNextInstruction) } - fn run_current_memory(&mut self, context: &mut FunctionContext) -> Result { + fn run_current_memory( + &mut self, + context: &mut FunctionContext, + ) -> Result { let m = context .memory() .expect("Due to validation memory should exists"); let s = m.current_size().0; - self - .value_stack - .push(RuntimeValue::I32(s as i32))?; + self.value_stack.push(RuntimeValueInternal(s as _))?; Ok(InstructionOutcome::RunNextInstruction) } - fn run_grow_memory(&mut self, context: &mut FunctionContext) -> Result { - let pages: u32 = self - .value_stack - .pop_as(); + fn run_grow_memory( + &mut self, + context: &mut FunctionContext, + ) -> Result { + let pages: u32 = self.value_stack.pop_as(); let m = context .memory() .expect("Due to validation memory should exists"); @@ -724,142 +850,161 @@ impl Interpreter { Ok(Pages(new_size)) => new_size as u32, Err(_) => u32::MAX, // Returns -1 (or 0xFFFFFFFF) in case of error. }; - self - .value_stack - .push(RuntimeValue::I32(m as i32))?; + self.value_stack.push(RuntimeValueInternal(m as _))?; Ok(InstructionOutcome::RunNextInstruction) } fn run_const(&mut self, val: RuntimeValue) -> Result { - self - .value_stack - .push(val) + self.value_stack + .push(val.into()) .map_err(Into::into) .map(|_| InstructionOutcome::RunNextInstruction) } fn run_relop(&mut self, f: F) -> Result where - T: FromRuntimeValue, + T: FromRuntimeValueInternal, F: FnOnce(T, T) -> bool, { - let (left, right) = self - .value_stack - .pop_pair_as::(); + let (left, right) = self.value_stack.pop_pair_as::(); let v = if f(left, right) { - RuntimeValue::I32(1) + RuntimeValueInternal(1) } else { - RuntimeValue::I32(0) + RuntimeValueInternal(0) }; self.value_stack.push(v)?; Ok(InstructionOutcome::RunNextInstruction) } fn run_eqz(&mut self) -> Result - where T: FromRuntimeValue, T: PartialEq + Default { - let v = self - .value_stack - .pop_as::(); - let v = RuntimeValue::I32(if v == Default::default() { 1 } else { 0 }); + where + T: FromRuntimeValueInternal, + T: PartialEq + Default, + { + let v = self.value_stack.pop_as::(); + let v = RuntimeValueInternal(if v == Default::default() { 1 } else { 0 }); self.value_stack.push(v)?; Ok(InstructionOutcome::RunNextInstruction) } fn run_eq(&mut self) -> Result - where T: FromRuntimeValue + PartialEq + where + T: FromRuntimeValueInternal + PartialEq, { self.run_relop(|left: T, right: T| left == right) } fn run_ne(&mut self) -> Result - where T: FromRuntimeValue + PartialEq { + where + T: FromRuntimeValueInternal + PartialEq, + { self.run_relop(|left: T, right: T| left != right) } fn run_lt(&mut self) -> Result - where T: FromRuntimeValue + PartialOrd { + where + T: FromRuntimeValueInternal + PartialOrd, + { self.run_relop(|left: T, right: T| left < right) } fn run_gt(&mut self) -> Result - where T: FromRuntimeValue + PartialOrd { + where + T: FromRuntimeValueInternal + PartialOrd, + { self.run_relop(|left: T, right: T| left > right) } fn run_lte(&mut self) -> Result - where T: FromRuntimeValue + PartialOrd { + where + T: FromRuntimeValueInternal + PartialOrd, + { self.run_relop(|left: T, right: T| left <= right) } fn run_gte(&mut self) -> Result - where T: FromRuntimeValue + PartialOrd { + where + T: FromRuntimeValueInternal + PartialOrd, + { self.run_relop(|left: T, right: T| left >= right) } fn run_unop(&mut self, f: F) -> Result where F: FnOnce(T) -> U, - T: FromRuntimeValue, - RuntimeValue: From + T: FromRuntimeValueInternal, + RuntimeValueInternal: From, { - let v = self - .value_stack - .pop_as::(); + let v = self.value_stack.pop_as::(); let v = f(v); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_clz(&mut self) -> Result - where RuntimeValue: From, T: Integer + FromRuntimeValue { + where + RuntimeValueInternal: From, + T: Integer + FromRuntimeValueInternal, + { self.run_unop(|v: T| v.leading_zeros()) } fn run_ctz(&mut self) -> Result - where RuntimeValue: From, T: Integer + FromRuntimeValue { + where + RuntimeValueInternal: From, + T: Integer + FromRuntimeValueInternal, + { self.run_unop(|v: T| v.trailing_zeros()) } fn run_popcnt(&mut self) -> Result - where RuntimeValue: From, T: Integer + FromRuntimeValue { + where + RuntimeValueInternal: From, + T: Integer + FromRuntimeValueInternal, + { self.run_unop(|v: T| v.count_ones()) } fn run_add(&mut self) -> Result - where RuntimeValue: From, T: ArithmeticOps + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From, + T: ArithmeticOps + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.add(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_sub(&mut self) -> Result - where RuntimeValue: From, T: ArithmeticOps + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From, + T: ArithmeticOps + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.sub(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_mul(&mut self) -> Result - where RuntimeValue: From, T: ArithmeticOps + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From, + T: ArithmeticOps + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.mul(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_div(&mut self) -> Result - where RuntimeValue: From, T: TransmuteInto + FromRuntimeValue, U: ArithmeticOps + TransmuteInto { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From, + T: TransmuteInto + FromRuntimeValueInternal, + U: ArithmeticOps + TransmuteInto, + { + let (left, right) = self.value_stack.pop_pair_as::(); let (left, right) = (left.transmute_into(), right.transmute_into()); let v = left.div(right)?; let v = v.transmute_into(); @@ -868,10 +1013,12 @@ impl Interpreter { } fn run_rem(&mut self) -> Result - where RuntimeValue: From, T: TransmuteInto + FromRuntimeValue, U: Integer + TransmuteInto { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From, + T: TransmuteInto + FromRuntimeValueInternal, + U: Integer + TransmuteInto, + { + let (left, right) = self.value_stack.pop_pair_as::(); let (left, right) = (left.transmute_into(), right.transmute_into()); let v = left.rem(right)?; let v = v.transmute_into(); @@ -880,50 +1027,57 @@ impl Interpreter { } fn run_and(&mut self) -> Result - where RuntimeValue: From<::Output>, T: ops::BitAnd + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From<::Output>, + T: ops::BitAnd + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.bitand(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_or(&mut self) -> Result - where RuntimeValue: From<::Output>, T: ops::BitOr + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From<::Output>, + T: ops::BitOr + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.bitor(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_xor(&mut self) -> Result - where RuntimeValue: From<::Output>, T: ops::BitXor + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From<::Output>, + T: ops::BitXor + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.bitxor(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_shl(&mut self, mask: T) -> Result - where RuntimeValue: From<>::Output>, T: ops::Shl + ops::BitAnd + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From<>::Output>, + T: ops::Shl + ops::BitAnd + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.shl(right & mask); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_shr(&mut self, mask: U) -> Result - where RuntimeValue: From, T: TransmuteInto + FromRuntimeValue, U: ops::Shr + ops::BitAnd, >::Output: TransmuteInto { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From, + T: TransmuteInto + FromRuntimeValueInternal, + U: ops::Shr + ops::BitAnd, + >::Output: TransmuteInto, + { + let (left, right) = self.value_stack.pop_pair_as::(); let (left, right) = (left.transmute_into(), right.transmute_into()); let v = left.shr(right & mask); let v = v.transmute_into(); @@ -932,111 +1086,131 @@ impl Interpreter { } fn run_rotl(&mut self) -> Result - where RuntimeValue: From, T: Integer + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From, + T: Integer + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.rotl(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_rotr(&mut self) -> Result - where RuntimeValue: From, T: Integer + FromRuntimeValue + where + RuntimeValueInternal: From, + T: Integer + FromRuntimeValueInternal, { - let (left, right) = self - .value_stack - .pop_pair_as::(); + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.rotr(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_abs(&mut self) -> Result - where RuntimeValue: From, T: Float + FromRuntimeValue + where + RuntimeValueInternal: From, + T: Float + FromRuntimeValueInternal, { self.run_unop(|v: T| v.abs()) } fn run_neg(&mut self) -> Result where - RuntimeValue: From<::Output>, - T: ops::Neg + FromRuntimeValue + RuntimeValueInternal: From<::Output>, + T: ops::Neg + FromRuntimeValueInternal, { self.run_unop(|v: T| v.neg()) } fn run_ceil(&mut self) -> Result - where RuntimeValue: From, T: Float + FromRuntimeValue + where + RuntimeValueInternal: From, + T: Float + FromRuntimeValueInternal, { self.run_unop(|v: T| v.ceil()) } fn run_floor(&mut self) -> Result - where RuntimeValue: From, T: Float + FromRuntimeValue + where + RuntimeValueInternal: From, + T: Float + FromRuntimeValueInternal, { self.run_unop(|v: T| v.floor()) } fn run_trunc(&mut self) -> Result - where RuntimeValue: From, T: Float + FromRuntimeValue + where + RuntimeValueInternal: From, + T: Float + FromRuntimeValueInternal, { self.run_unop(|v: T| v.trunc()) } fn run_nearest(&mut self) -> Result - where RuntimeValue: From, T: Float + FromRuntimeValue + where + RuntimeValueInternal: From, + T: Float + FromRuntimeValueInternal, { self.run_unop(|v: T| v.nearest()) } fn run_sqrt(&mut self) -> Result - where RuntimeValue: From, T: Float + FromRuntimeValue + where + RuntimeValueInternal: From, + T: Float + FromRuntimeValueInternal, { self.run_unop(|v: T| v.sqrt()) } fn run_min(&mut self) -> Result - where RuntimeValue: From, T: Float + FromRuntimeValue + where + RuntimeValueInternal: From, + T: Float + FromRuntimeValueInternal, { - let (left, right) = self - .value_stack - .pop_pair_as::(); + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.min(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_max(&mut self) -> Result - where RuntimeValue: From, T: Float + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From, + T: Float + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.max(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_copysign(&mut self) -> Result - where RuntimeValue: From, T: Float + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From, + T: Float + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.copysign(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_wrap(&mut self) -> Result - where RuntimeValue: From, T: WrapInto + FromRuntimeValue { + where + RuntimeValueInternal: From, + T: WrapInto + FromRuntimeValueInternal, + { self.run_unop(|v: T| v.wrap_into()) } fn run_trunc_to_int(&mut self) -> Result - where RuntimeValue: From, T: TryTruncateInto + FromRuntimeValue, U: TransmuteInto, { - let v = self - .value_stack - .pop_as::(); + where + RuntimeValueInternal: From, + T: TryTruncateInto + FromRuntimeValueInternal, + U: TransmuteInto, + { + let v = self.value_stack.pop_as::(); v.try_truncate_into() .map(|v| v.transmute_into()) @@ -1046,11 +1220,11 @@ impl Interpreter { fn run_extend(&mut self) -> Result where - RuntimeValue: From, T: ExtendInto + FromRuntimeValue, U: TransmuteInto + RuntimeValueInternal: From, + T: ExtendInto + FromRuntimeValueInternal, + U: TransmuteInto, { - let v = self - .value_stack - .pop_as::(); + let v = self.value_stack.pop_as::(); let v = v.extend_into().transmute_into(); self.value_stack.push(v.into())?; @@ -1060,11 +1234,11 @@ impl Interpreter { fn run_reinterpret(&mut self) -> Result where - RuntimeValue: From, T: FromRuntimeValue, T: TransmuteInto + RuntimeValueInternal: From, + T: FromRuntimeValueInternal, + T: TransmuteInto, { - let v = self - .value_stack - .pop_as::(); + let v = self.value_stack.pop_as::(); let v = v.transmute_into(); self.value_stack.push(v.into())?; @@ -1105,18 +1279,20 @@ impl FunctionContext { self.is_initialized } - pub fn initialize(&mut self, locals: &[Local], value_stack: &mut ValueStack) -> Result<(), TrapKind> { + pub fn initialize( + &mut self, + locals: &[Local], + value_stack: &mut ValueStack, + ) -> Result<(), TrapKind> { debug_assert!(!self.is_initialized); - let locals = locals.iter() - .flat_map(|l| repeat(l.value_type()).take(l.count() as usize)) - .map(::types::ValueType::from_elements) - .map(RuntimeValue::default) - .collect::>(); + let num_locals = locals.iter().map(|l| l.count() as usize).sum(); + let locals = vec![Default::default(); num_locals]; // TODO: Replace with extend. for local in locals { - value_stack.push(local) + value_stack + .push(local) .map_err(|_| TrapKind::StackOverflow)?; } @@ -1150,27 +1326,29 @@ fn prepare_function_args( signature: &Signature, caller_stack: &mut ValueStack, ) -> Vec { - let mut args = signature + let mut out = signature .params() .iter() - .map(|_| caller_stack.pop()) + .rev() + .map(|¶m_ty| caller_stack.pop().with_type(param_ty)) .collect::>(); - args.reverse(); - check_function_args(signature, &args).expect("Due to validation arguments should match"); - args + out.reverse(); + out } pub fn check_function_args(signature: &Signature, args: &[RuntimeValue]) -> Result<(), Trap> { if signature.params().len() != args.len() { - return Err( - TrapKind::UnexpectedSignature.into() - ); + return Err(TrapKind::UnexpectedSignature.into()); } - if signature.params().iter().zip(args).any(|(expected_type, param_value)| { - let actual_type = param_value.value_type(); - &actual_type != expected_type - }) { + if signature + .params() + .iter() + .zip(args) + .any(|(expected_type, param_value)| { + let actual_type = param_value.value_type(); + &actual_type != expected_type + }) { return Err(TrapKind::UnexpectedSignature.into()); } @@ -1179,7 +1357,7 @@ pub fn check_function_args(signature: &Signature, args: &[RuntimeValue]) -> Resu #[derive(Debug)] struct ValueStack { - buf: Box<[RuntimeValue]>, + buf: Box<[RuntimeValueInternal]>, /// Index of the first free place in the stack. sp: usize, } @@ -1187,7 +1365,7 @@ struct ValueStack { impl ValueStack { fn with_limit(limit: usize) -> ValueStack { let mut buf = Vec::new(); - buf.resize(limit, RuntimeValue::I32(0)); + buf.resize(limit, RuntimeValueInternal(0)); ValueStack { buf: buf.into_boxed_slice(), @@ -1209,16 +1387,17 @@ impl ValueStack { #[inline] fn pop_as(&mut self) -> T where - T: FromRuntimeValue, + T: FromRuntimeValueInternal, { let value = self.pop(); - value.try_into().expect("Due to validation stack top's type should match") + + T::from_runtime_value_internal(value) } #[inline] fn pop_pair_as(&mut self) -> (T, T) where - T: FromRuntimeValue, + T: FromRuntimeValueInternal, { let right = self.pop_as(); let left = self.pop_as(); @@ -1226,7 +1405,13 @@ impl ValueStack { } #[inline] - fn pop_triple(&mut self) -> (RuntimeValue, RuntimeValue, RuntimeValue) { + fn pop_triple( + &mut self, + ) -> ( + RuntimeValueInternal, + RuntimeValueInternal, + RuntimeValueInternal, + ) { let right = self.pop(); let mid = self.pop(); let left = self.pop(); @@ -1234,28 +1419,31 @@ impl ValueStack { } #[inline] - fn top(&self) -> &RuntimeValue { + fn top(&self) -> &RuntimeValueInternal { self.pick(1) } - fn pick(&self, depth: usize) -> &RuntimeValue { + fn pick(&self, depth: usize) -> &RuntimeValueInternal { &self.buf[self.sp - depth] } #[inline] - fn pick_mut(&mut self, depth: usize) -> &mut RuntimeValue { + fn pick_mut(&mut self, depth: usize) -> &mut RuntimeValueInternal { &mut self.buf[self.sp - depth] } #[inline] - fn pop(&mut self) -> RuntimeValue { + fn pop(&mut self) -> RuntimeValueInternal { self.sp -= 1; self.buf[self.sp] } #[inline] - fn push(&mut self, value: RuntimeValue) -> Result<(), TrapKind> { - let cell = self.buf.get_mut(self.sp).ok_or_else(|| TrapKind::StackOverflow)?; + fn push(&mut self, value: RuntimeValueInternal) -> Result<(), TrapKind> { + let cell = self + .buf + .get_mut(self.sp) + .ok_or_else(|| TrapKind::StackOverflow)?; *cell = value; self.sp += 1; Ok(()) diff --git a/src/value.rs b/src/value.rs index 87eabb5..bacc991 100644 --- a/src/value.rs +++ b/src/value.rs @@ -1,6 +1,7 @@ use byteorder::{ByteOrder, LittleEndian}; -use nan_preserving_float::{F32, F64}; use core::{f32, i32, i64, u32, u64}; +use nan_preserving_float::{F32, F64}; +use types::ValueType; use TrapKind; #[derive(Debug)] @@ -36,7 +37,10 @@ pub enum RuntimeValue { /// [`I32`]: enum.RuntimeValue.html#variant.I32 /// [`F64`]: enum.RuntimeValue.html#variant.F64 /// [`RuntimeValue`]: enum.RuntimeValue.html -pub trait FromRuntimeValue where Self: Sized { +pub trait FromRuntimeValue +where + Self: Sized, +{ /// Create a value of type `Self` from a given [`RuntimeValue`]. /// /// Returns `None` if the [`RuntimeValue`] is of type different than @@ -71,9 +75,12 @@ pub trait TransmuteInto { } /// Convert from and to little endian. -pub trait LittleEndianConvert where Self: Sized { +pub trait LittleEndianConvert +where + Self: Sized, +{ /// Convert to little endian buffer. - fn into_little_endian(self, buffer: &mut[u8]); + fn into_little_endian(self, buffer: &mut [u8]); /// Convert from little endian buffer. fn from_little_endian(buffer: &[u8]) -> Result; } @@ -132,12 +139,12 @@ pub trait Float: ArithmeticOps { impl RuntimeValue { /// Creates new default value of given type. - pub fn default(value_type: ::types::ValueType) -> Self { + pub fn default(value_type: ValueType) -> Self { match value_type { - ::types::ValueType::I32 => RuntimeValue::I32(0), - ::types::ValueType::I64 => RuntimeValue::I64(0), - ::types::ValueType::F32 => RuntimeValue::F32(0f32.into()), - ::types::ValueType::F64 => RuntimeValue::F64(0f64.into()), + ValueType::I32 => RuntimeValue::I32(0), + ValueType::I64 => RuntimeValue::I64(0), + ValueType::F32 => RuntimeValue::F32(0f32.into()), + ValueType::F64 => RuntimeValue::F64(0f64.into()), } } @@ -152,12 +159,12 @@ impl RuntimeValue { } /// Get variable type for this value. - pub fn value_type(&self) -> ::types::ValueType { + pub fn value_type(&self) -> ValueType { match *self { - RuntimeValue::I32(_) => ::types::ValueType::I32, - RuntimeValue::I64(_) => ::types::ValueType::I64, - RuntimeValue::F32(_) => ::types::ValueType::F32, - RuntimeValue::F64(_) => ::types::ValueType::F64, + RuntimeValue::I32(_) => ValueType::I32, + RuntimeValue::I64(_) => ValueType::I64, + RuntimeValue::F32(_) => ValueType::F32, + RuntimeValue::F64(_) => ValueType::F64, } } @@ -461,7 +468,7 @@ macro_rules! impl_transmute_into_self { self } } - } + }; } impl_transmute_into_self!(i32); @@ -478,7 +485,7 @@ macro_rules! impl_transmute_into_as { self as $into } } - } + }; } impl_transmute_into_as!(i8, u8); @@ -529,139 +536,160 @@ impl_transmute_into_npf!(F32, f32, i32, u32); impl_transmute_into_npf!(F64, f64, i64, u64); impl TransmuteInto for f32 { - fn transmute_into(self) -> i32 { self.to_bits() as i32 } + fn transmute_into(self) -> i32 { + self.to_bits() as i32 + } } impl TransmuteInto for f64 { - fn transmute_into(self) -> i64 { self.to_bits() as i64 } + fn transmute_into(self) -> i64 { + self.to_bits() as i64 + } } impl TransmuteInto for i32 { - fn transmute_into(self) -> f32 { f32::from_bits(self as u32) } + fn transmute_into(self) -> f32 { + f32::from_bits(self as u32) + } } impl TransmuteInto for i64 { - fn transmute_into(self) -> f64 { f64::from_bits(self as u64) } + fn transmute_into(self) -> f64 { + f64::from_bits(self as u64) + } } impl TransmuteInto for u32 { - fn transmute_into(self) -> i32 { self as _ } + fn transmute_into(self) -> i32 { + self as _ + } } impl TransmuteInto for u64 { - fn transmute_into(self) -> i64 { self as _ } + fn transmute_into(self) -> i64 { + self as _ + } } impl LittleEndianConvert for i8 { - fn into_little_endian(self, buffer: &mut[u8]) { + fn into_little_endian(self, buffer: &mut [u8]) { buffer[0] = self as u8; } fn from_little_endian(buffer: &[u8]) -> Result { - buffer.get(0) + buffer + .get(0) .map(|v| *v as i8) .ok_or_else(|| Error::InvalidLittleEndianBuffer) } } impl LittleEndianConvert for u8 { - fn into_little_endian(self, buffer: &mut[u8]) { + fn into_little_endian(self, buffer: &mut [u8]) { buffer[0] = self; } fn from_little_endian(buffer: &[u8]) -> Result { - buffer.get(0) + buffer + .get(0) .cloned() .ok_or_else(|| Error::InvalidLittleEndianBuffer) } } impl LittleEndianConvert for i16 { - fn into_little_endian(self, buffer: &mut[u8]) { + fn into_little_endian(self, buffer: &mut [u8]) { LittleEndian::write_i16(buffer, self); } fn from_little_endian(buffer: &[u8]) -> Result { - buffer.get(0..2) + buffer + .get(0..2) .map(LittleEndian::read_i16) .ok_or_else(|| Error::InvalidLittleEndianBuffer) } } impl LittleEndianConvert for u16 { - fn into_little_endian(self, buffer: &mut[u8]) { + fn into_little_endian(self, buffer: &mut [u8]) { LittleEndian::write_u16(buffer, self); } fn from_little_endian(buffer: &[u8]) -> Result { - buffer.get(0..2) + buffer + .get(0..2) .map(LittleEndian::read_u16) .ok_or_else(|| Error::InvalidLittleEndianBuffer) } } impl LittleEndianConvert for i32 { - fn into_little_endian(self, buffer: &mut[u8]) { + fn into_little_endian(self, buffer: &mut [u8]) { LittleEndian::write_i32(buffer, self); } fn from_little_endian(buffer: &[u8]) -> Result { - buffer.get(0..4) + buffer + .get(0..4) .map(LittleEndian::read_i32) .ok_or_else(|| Error::InvalidLittleEndianBuffer) } } impl LittleEndianConvert for u32 { - fn into_little_endian(self, buffer: &mut[u8]) { + fn into_little_endian(self, buffer: &mut [u8]) { LittleEndian::write_u32(buffer, self); } fn from_little_endian(buffer: &[u8]) -> Result { - buffer.get(0..4) + buffer + .get(0..4) .map(LittleEndian::read_u32) .ok_or_else(|| Error::InvalidLittleEndianBuffer) } } impl LittleEndianConvert for i64 { - fn into_little_endian(self, buffer: &mut[u8]) { + fn into_little_endian(self, buffer: &mut [u8]) { LittleEndian::write_i64(buffer, self); } fn from_little_endian(buffer: &[u8]) -> Result { - buffer.get(0..8) + buffer + .get(0..8) .map(LittleEndian::read_i64) .ok_or_else(|| Error::InvalidLittleEndianBuffer) } } impl LittleEndianConvert for f32 { - fn into_little_endian(self, buffer: &mut[u8]) { + fn into_little_endian(self, buffer: &mut [u8]) { LittleEndian::write_f32(buffer, self); } fn from_little_endian(buffer: &[u8]) -> Result { - buffer.get(0..4) + buffer + .get(0..4) .map(LittleEndian::read_f32) .ok_or_else(|| Error::InvalidLittleEndianBuffer) } } impl LittleEndianConvert for f64 { - fn into_little_endian(self, buffer: &mut[u8]) { + fn into_little_endian(self, buffer: &mut [u8]) { LittleEndian::write_f64(buffer, self); } fn from_little_endian(buffer: &[u8]) -> Result { - buffer.get(0..8) + buffer + .get(0..8) .map(LittleEndian::read_f64) .ok_or_else(|| Error::InvalidLittleEndianBuffer) } } impl LittleEndianConvert for F32 { - fn into_little_endian(self, buffer: &mut[u8]) { + fn into_little_endian(self, buffer: &mut [u8]) { (self.to_bits() as i32).into_little_endian(buffer) } @@ -671,7 +699,7 @@ impl LittleEndianConvert for F32 { } impl LittleEndianConvert for F64 { - fn into_little_endian(self, buffer: &mut[u8]) { + fn into_little_endian(self, buffer: &mut [u8]) { (self.to_bits() as i64).into_little_endian(buffer) } @@ -683,14 +711,19 @@ impl LittleEndianConvert for F64 { macro_rules! impl_integer_arithmetic_ops { ($type: ident) => { impl ArithmeticOps<$type> for $type { - fn add(self, other: $type) -> $type { self.wrapping_add(other) } - fn sub(self, other: $type) -> $type { self.wrapping_sub(other) } - fn mul(self, other: $type) -> $type { self.wrapping_mul(other) } + fn add(self, other: $type) -> $type { + self.wrapping_add(other) + } + fn sub(self, other: $type) -> $type { + self.wrapping_sub(other) + } + fn mul(self, other: $type) -> $type { + self.wrapping_mul(other) + } fn div(self, other: $type) -> Result<$type, TrapKind> { if other == 0 { Err(TrapKind::DivisionByZero) - } - else { + } else { let (result, overflow) = self.overflowing_div(other); if overflow { Err(TrapKind::InvalidConversionToInt) @@ -700,7 +733,7 @@ macro_rules! impl_integer_arithmetic_ops { } } } - } + }; } impl_integer_arithmetic_ops!(i32); @@ -711,12 +744,20 @@ impl_integer_arithmetic_ops!(u64); macro_rules! impl_float_arithmetic_ops { ($type: ident) => { impl ArithmeticOps<$type> for $type { - fn add(self, other: $type) -> $type { self + other } - fn sub(self, other: $type) -> $type { self - other } - fn mul(self, other: $type) -> $type { self * other } - fn div(self, other: $type) -> Result<$type, TrapKind> { Ok(self / other) } + fn add(self, other: $type) -> $type { + self + other + } + fn sub(self, other: $type) -> $type { + self - other + } + fn mul(self, other: $type) -> $type { + self * other + } + fn div(self, other: $type) -> Result<$type, TrapKind> { + Ok(self / other) + } } - } + }; } impl_float_arithmetic_ops!(f32); @@ -727,17 +768,30 @@ impl_float_arithmetic_ops!(F64); macro_rules! impl_integer { ($type: ident) => { impl Integer<$type> for $type { - fn leading_zeros(self) -> $type { self.leading_zeros() as $type } - fn trailing_zeros(self) -> $type { self.trailing_zeros() as $type } - fn count_ones(self) -> $type { self.count_ones() as $type } - fn rotl(self, other: $type) -> $type { self.rotate_left(other as u32) } - fn rotr(self, other: $type) -> $type { self.rotate_right(other as u32) } + fn leading_zeros(self) -> $type { + self.leading_zeros() as $type + } + fn trailing_zeros(self) -> $type { + self.trailing_zeros() as $type + } + fn count_ones(self) -> $type { + self.count_ones() as $type + } + fn rotl(self, other: $type) -> $type { + self.rotate_left(other as u32) + } + fn rotr(self, other: $type) -> $type { + self.rotate_right(other as u32) + } fn rem(self, other: $type) -> Result<$type, TrapKind> { - if other == 0 { Err(TrapKind::DivisionByZero) } - else { Ok(self.wrapping_rem(other)) } + if other == 0 { + Err(TrapKind::DivisionByZero) + } else { + Ok(self.wrapping_rem(other)) + } } } - } + }; } impl_integer!(i32);