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)`
This commit is contained in:
Jef 2018-10-31 16:01:20 +01:00 committed by Sergey Pepyakin
parent 1c04be64f8
commit c877d64508
2 changed files with 612 additions and 370 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
use byteorder::{ByteOrder, LittleEndian}; use byteorder::{ByteOrder, LittleEndian};
use nan_preserving_float::{F32, F64};
use core::{f32, i32, i64, u32, u64}; use core::{f32, i32, i64, u32, u64};
use nan_preserving_float::{F32, F64};
use types::ValueType;
use TrapKind; use TrapKind;
#[derive(Debug)] #[derive(Debug)]
@ -36,7 +37,10 @@ pub enum RuntimeValue {
/// [`I32`]: enum.RuntimeValue.html#variant.I32 /// [`I32`]: enum.RuntimeValue.html#variant.I32
/// [`F64`]: enum.RuntimeValue.html#variant.F64 /// [`F64`]: enum.RuntimeValue.html#variant.F64
/// [`RuntimeValue`]: enum.RuntimeValue.html /// [`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`]. /// Create a value of type `Self` from a given [`RuntimeValue`].
/// ///
/// Returns `None` if the [`RuntimeValue`] is of type different than /// Returns `None` if the [`RuntimeValue`] is of type different than
@ -71,9 +75,12 @@ pub trait TransmuteInto<T> {
} }
/// Convert from and to little endian. /// Convert from and to little endian.
pub trait LittleEndianConvert where Self: Sized { pub trait LittleEndianConvert
where
Self: Sized,
{
/// Convert to little endian buffer. /// 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. /// Convert from little endian buffer.
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error>; fn from_little_endian(buffer: &[u8]) -> Result<Self, Error>;
} }
@ -132,12 +139,12 @@ pub trait Float<T>: ArithmeticOps<T> {
impl RuntimeValue { impl RuntimeValue {
/// Creates new default value of given type. /// 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 { match value_type {
::types::ValueType::I32 => RuntimeValue::I32(0), ValueType::I32 => RuntimeValue::I32(0),
::types::ValueType::I64 => RuntimeValue::I64(0), ValueType::I64 => RuntimeValue::I64(0),
::types::ValueType::F32 => RuntimeValue::F32(0f32.into()), ValueType::F32 => RuntimeValue::F32(0f32.into()),
::types::ValueType::F64 => RuntimeValue::F64(0f64.into()), ValueType::F64 => RuntimeValue::F64(0f64.into()),
} }
} }
@ -152,12 +159,12 @@ impl RuntimeValue {
} }
/// Get variable type for this value. /// Get variable type for this value.
pub fn value_type(&self) -> ::types::ValueType { pub fn value_type(&self) -> ValueType {
match *self { match *self {
RuntimeValue::I32(_) => ::types::ValueType::I32, RuntimeValue::I32(_) => ValueType::I32,
RuntimeValue::I64(_) => ::types::ValueType::I64, RuntimeValue::I64(_) => ValueType::I64,
RuntimeValue::F32(_) => ::types::ValueType::F32, RuntimeValue::F32(_) => ValueType::F32,
RuntimeValue::F64(_) => ::types::ValueType::F64, RuntimeValue::F64(_) => ValueType::F64,
} }
} }
@ -461,7 +468,7 @@ macro_rules! impl_transmute_into_self {
self self
} }
} }
} };
} }
impl_transmute_into_self!(i32); impl_transmute_into_self!(i32);
@ -478,7 +485,7 @@ macro_rules! impl_transmute_into_as {
self as $into self as $into
} }
} }
} };
} }
impl_transmute_into_as!(i8, u8); 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_transmute_into_npf!(F64, f64, i64, u64);
impl TransmuteInto<i32> for f32 { impl TransmuteInto<i32> for f32 {
fn transmute_into(self) -> i32 { self.to_bits() as i32 } fn transmute_into(self) -> i32 {
self.to_bits() as i32
}
} }
impl TransmuteInto<i64> for f64 { impl TransmuteInto<i64> for f64 {
fn transmute_into(self) -> i64 { self.to_bits() as i64 } fn transmute_into(self) -> i64 {
self.to_bits() as i64
}
} }
impl TransmuteInto<f32> for i32 { impl TransmuteInto<f32> 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<f64> for i64 { impl TransmuteInto<f64> 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<i32> for u32 { impl TransmuteInto<i32> for u32 {
fn transmute_into(self) -> i32 { self as _ } fn transmute_into(self) -> i32 {
self as _
}
} }
impl TransmuteInto<i64> for u64 { impl TransmuteInto<i64> for u64 {
fn transmute_into(self) -> i64 { self as _ } fn transmute_into(self) -> i64 {
self as _
}
} }
impl LittleEndianConvert for i8 { 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; buffer[0] = self as u8;
} }
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> { fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> {
buffer.get(0) buffer
.get(0)
.map(|v| *v as i8) .map(|v| *v as i8)
.ok_or_else(|| Error::InvalidLittleEndianBuffer) .ok_or_else(|| Error::InvalidLittleEndianBuffer)
} }
} }
impl LittleEndianConvert for u8 { impl LittleEndianConvert for u8 {
fn into_little_endian(self, buffer: &mut[u8]) { fn into_little_endian(self, buffer: &mut [u8]) {
buffer[0] = self; buffer[0] = self;
} }
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> { fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> {
buffer.get(0) buffer
.get(0)
.cloned() .cloned()
.ok_or_else(|| Error::InvalidLittleEndianBuffer) .ok_or_else(|| Error::InvalidLittleEndianBuffer)
} }
} }
impl LittleEndianConvert for i16 { 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); LittleEndian::write_i16(buffer, self);
} }
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> { fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> {
buffer.get(0..2) buffer
.get(0..2)
.map(LittleEndian::read_i16) .map(LittleEndian::read_i16)
.ok_or_else(|| Error::InvalidLittleEndianBuffer) .ok_or_else(|| Error::InvalidLittleEndianBuffer)
} }
} }
impl LittleEndianConvert for u16 { 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); LittleEndian::write_u16(buffer, self);
} }
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> { fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> {
buffer.get(0..2) buffer
.get(0..2)
.map(LittleEndian::read_u16) .map(LittleEndian::read_u16)
.ok_or_else(|| Error::InvalidLittleEndianBuffer) .ok_or_else(|| Error::InvalidLittleEndianBuffer)
} }
} }
impl LittleEndianConvert for i32 { 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); LittleEndian::write_i32(buffer, self);
} }
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> { fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> {
buffer.get(0..4) buffer
.get(0..4)
.map(LittleEndian::read_i32) .map(LittleEndian::read_i32)
.ok_or_else(|| Error::InvalidLittleEndianBuffer) .ok_or_else(|| Error::InvalidLittleEndianBuffer)
} }
} }
impl LittleEndianConvert for u32 { 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); LittleEndian::write_u32(buffer, self);
} }
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> { fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> {
buffer.get(0..4) buffer
.get(0..4)
.map(LittleEndian::read_u32) .map(LittleEndian::read_u32)
.ok_or_else(|| Error::InvalidLittleEndianBuffer) .ok_or_else(|| Error::InvalidLittleEndianBuffer)
} }
} }
impl LittleEndianConvert for i64 { 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); LittleEndian::write_i64(buffer, self);
} }
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> { fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> {
buffer.get(0..8) buffer
.get(0..8)
.map(LittleEndian::read_i64) .map(LittleEndian::read_i64)
.ok_or_else(|| Error::InvalidLittleEndianBuffer) .ok_or_else(|| Error::InvalidLittleEndianBuffer)
} }
} }
impl LittleEndianConvert for f32 { 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); LittleEndian::write_f32(buffer, self);
} }
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> { fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> {
buffer.get(0..4) buffer
.get(0..4)
.map(LittleEndian::read_f32) .map(LittleEndian::read_f32)
.ok_or_else(|| Error::InvalidLittleEndianBuffer) .ok_or_else(|| Error::InvalidLittleEndianBuffer)
} }
} }
impl LittleEndianConvert for f64 { 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); LittleEndian::write_f64(buffer, self);
} }
fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> { fn from_little_endian(buffer: &[u8]) -> Result<Self, Error> {
buffer.get(0..8) buffer
.get(0..8)
.map(LittleEndian::read_f64) .map(LittleEndian::read_f64)
.ok_or_else(|| Error::InvalidLittleEndianBuffer) .ok_or_else(|| Error::InvalidLittleEndianBuffer)
} }
} }
impl LittleEndianConvert for F32 { 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) (self.to_bits() as i32).into_little_endian(buffer)
} }
@ -671,7 +699,7 @@ impl LittleEndianConvert for F32 {
} }
impl LittleEndianConvert for F64 { 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) (self.to_bits() as i64).into_little_endian(buffer)
} }
@ -683,14 +711,19 @@ impl LittleEndianConvert for F64 {
macro_rules! impl_integer_arithmetic_ops { macro_rules! impl_integer_arithmetic_ops {
($type: ident) => { ($type: ident) => {
impl ArithmeticOps<$type> for $type { impl ArithmeticOps<$type> for $type {
fn add(self, other: $type) -> $type { self.wrapping_add(other) } fn add(self, other: $type) -> $type {
fn sub(self, other: $type) -> $type { self.wrapping_sub(other) } self.wrapping_add(other)
fn mul(self, other: $type) -> $type { self.wrapping_mul(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> { fn div(self, other: $type) -> Result<$type, TrapKind> {
if other == 0 { if other == 0 {
Err(TrapKind::DivisionByZero) Err(TrapKind::DivisionByZero)
} } else {
else {
let (result, overflow) = self.overflowing_div(other); let (result, overflow) = self.overflowing_div(other);
if overflow { if overflow {
Err(TrapKind::InvalidConversionToInt) Err(TrapKind::InvalidConversionToInt)
@ -700,7 +733,7 @@ macro_rules! impl_integer_arithmetic_ops {
} }
} }
} }
} };
} }
impl_integer_arithmetic_ops!(i32); impl_integer_arithmetic_ops!(i32);
@ -711,12 +744,20 @@ impl_integer_arithmetic_ops!(u64);
macro_rules! impl_float_arithmetic_ops { macro_rules! impl_float_arithmetic_ops {
($type: ident) => { ($type: ident) => {
impl ArithmeticOps<$type> for $type { impl ArithmeticOps<$type> for $type {
fn add(self, other: $type) -> $type { self + other } fn add(self, other: $type) -> $type {
fn sub(self, other: $type) -> $type { self - other } self + other
fn mul(self, other: $type) -> $type { self * other } }
fn div(self, other: $type) -> Result<$type, TrapKind> { Ok(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); impl_float_arithmetic_ops!(f32);
@ -727,17 +768,30 @@ impl_float_arithmetic_ops!(F64);
macro_rules! impl_integer { macro_rules! impl_integer {
($type: ident) => { ($type: ident) => {
impl Integer<$type> for $type { impl Integer<$type> for $type {
fn leading_zeros(self) -> $type { self.leading_zeros() as $type } fn leading_zeros(self) -> $type {
fn trailing_zeros(self) -> $type { self.trailing_zeros() as $type } self.leading_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 trailing_zeros(self) -> $type {
fn rotr(self, other: $type) -> $type { self.rotate_right(other as u32) } 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> { fn rem(self, other: $type) -> Result<$type, TrapKind> {
if other == 0 { Err(TrapKind::DivisionByZero) } if other == 0 {
else { Ok(self.wrapping_rem(other)) } Err(TrapKind::DivisionByZero)
} else {
Ok(self.wrapping_rem(other))
}
} }
} }
} };
} }
impl_integer!(i32); impl_integer!(i32);