diff --git a/src/memory/mod.rs b/src/memory/mod.rs index f9f57234b9..59915aac39 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -197,13 +197,10 @@ impl MemoryInstance { /// Get value from memory at given offset. pub fn get_value(&self, offset: u32) -> Result { - let mut buffer = self.buffer.borrow_mut(); - let region = - self.checked_region(&mut buffer, offset as usize, ::core::mem::size_of::())?; - Ok( - T::from_little_endian(&buffer.as_slice_mut()[region.range()]) - .expect("Slice size is checked"), - ) + let mut bytes = <::Bytes as Default>::default(); + self.get_into(offset, bytes.as_mut())?; + let value = T::from_le_bytes(bytes); + Ok(value) } /// Copy data from memory at given offset. @@ -248,11 +245,8 @@ impl MemoryInstance { /// Copy value in the memory at given offset. pub fn set_value(&self, offset: u32, value: T) -> Result<(), Error> { - let mut buffer = self.buffer.borrow_mut(); - let range = self - .checked_region(&mut buffer, offset as usize, ::core::mem::size_of::())? - .range(); - value.into_little_endian(&mut buffer.as_slice_mut()[range]); + let bytes = T::into_le_bytes(value); + self.set(offset, bytes.as_ref())?; Ok(()) } diff --git a/src/value.rs b/src/value.rs index 9410f7b879..6a965ae1f2 100644 --- a/src/value.rs +++ b/src/value.rs @@ -77,16 +77,58 @@ pub trait TransmuteInto { fn transmute_into(self) -> T; } -/// Convert from and to little endian. -pub trait LittleEndianConvert -where - Self: Sized, -{ - /// Convert to little endian buffer. - fn into_little_endian(self, buffer: &mut [u8]); - /// Convert from little endian buffer. - fn from_little_endian(buffer: &[u8]) -> Result; +/// Types that can be converted from and to little endian bytes. +pub trait LittleEndianConvert { + /// The little endian bytes representation. + type Bytes: Default + AsRef<[u8]> + AsMut<[u8]>; + + /// Converts `self` into little endian bytes. + fn into_le_bytes(self) -> Self::Bytes; + + /// Converts little endian bytes into `Self`. + fn from_le_bytes(bytes: Self::Bytes) -> Self; +} + +macro_rules! impl_little_endian_convert_primitive { + ( $($primitive:ty),* $(,)? ) => { + $( + impl LittleEndianConvert for $primitive { + type Bytes = [::core::primitive::u8; ::core::mem::size_of::<$primitive>()]; + + fn into_le_bytes(self) -> Self::Bytes { + <$primitive>::to_le_bytes(self) + } + + fn from_le_bytes(bytes: Self::Bytes) -> Self { + <$primitive>::from_le_bytes(bytes) + } + } + )* + }; +} +impl_little_endian_convert_primitive!(u8, u16, u32, u64, i8, i16, i32, i64, f32, f64); + +macro_rules! impl_little_endian_convert_float { + ( $( struct $float_ty:ident($uint_ty:ty); )* $(,)? ) => { + $( + impl LittleEndianConvert for $float_ty { + type Bytes = <$uint_ty as LittleEndianConvert>::Bytes; + + fn into_le_bytes(self) -> Self::Bytes { + <$uint_ty>::into_le_bytes(self.to_bits()) + } + + fn from_le_bytes(bytes: Self::Bytes) -> Self { + Self::from_bits(<$uint_ty>::from_le_bytes(bytes)) + } + } + )* + }; } +impl_little_endian_convert_float!( + struct F32(u32); + struct F64(u64); +); /// Arithmetic operations. pub trait ArithmeticOps { @@ -565,171 +607,6 @@ impl TransmuteInto for u64 { } } -impl LittleEndianConvert for i8 { - fn into_little_endian(self, buffer: &mut [u8]) { - buffer[0] = self as u8; - } - - fn from_little_endian(buffer: &[u8]) -> Result { - buffer - .get(0) - .map(|v| *v as i8) - .ok_or(Error::InvalidLittleEndianBuffer) - } -} - -impl LittleEndianConvert for u8 { - fn into_little_endian(self, buffer: &mut [u8]) { - buffer[0] = self; - } - - fn from_little_endian(buffer: &[u8]) -> Result { - buffer - .get(0) - .cloned() - .ok_or(Error::InvalidLittleEndianBuffer) - } -} - -impl LittleEndianConvert for i16 { - fn into_little_endian(self, buffer: &mut [u8]) { - buffer.copy_from_slice(&self.to_le_bytes()); - } - - fn from_little_endian(buffer: &[u8]) -> Result { - let mut res = [0u8; 2]; - buffer - .get(0..2) - .map(|s| { - res.copy_from_slice(s); - Self::from_le_bytes(res) - }) - .ok_or(Error::InvalidLittleEndianBuffer) - } -} - -impl LittleEndianConvert for u16 { - fn into_little_endian(self, buffer: &mut [u8]) { - buffer.copy_from_slice(&self.to_le_bytes()); - } - - fn from_little_endian(buffer: &[u8]) -> Result { - let mut res = [0u8; 2]; - buffer - .get(0..2) - .map(|s| { - res.copy_from_slice(s); - Self::from_le_bytes(res) - }) - .ok_or(Error::InvalidLittleEndianBuffer) - } -} - -impl LittleEndianConvert for i32 { - fn into_little_endian(self, buffer: &mut [u8]) { - buffer.copy_from_slice(&self.to_le_bytes()); - } - - fn from_little_endian(buffer: &[u8]) -> Result { - let mut res = [0u8; 4]; - buffer - .get(0..4) - .map(|s| { - res.copy_from_slice(s); - Self::from_le_bytes(res) - }) - .ok_or(Error::InvalidLittleEndianBuffer) - } -} - -impl LittleEndianConvert for u32 { - fn into_little_endian(self, buffer: &mut [u8]) { - buffer.copy_from_slice(&self.to_le_bytes()); - } - - fn from_little_endian(buffer: &[u8]) -> Result { - let mut res = [0u8; 4]; - buffer - .get(0..4) - .map(|s| { - res.copy_from_slice(s); - Self::from_le_bytes(res) - }) - .ok_or(Error::InvalidLittleEndianBuffer) - } -} - -impl LittleEndianConvert for i64 { - fn into_little_endian(self, buffer: &mut [u8]) { - buffer.copy_from_slice(&self.to_le_bytes()); - } - - fn from_little_endian(buffer: &[u8]) -> Result { - let mut res = [0u8; 8]; - buffer - .get(0..8) - .map(|s| { - res.copy_from_slice(s); - Self::from_le_bytes(res) - }) - .ok_or(Error::InvalidLittleEndianBuffer) - } -} - -impl LittleEndianConvert for f32 { - fn into_little_endian(self, buffer: &mut [u8]) { - buffer.copy_from_slice(&self.to_bits().to_le_bytes()); - } - - fn from_little_endian(buffer: &[u8]) -> Result { - let mut res = [0u8; 4]; - buffer - .get(0..4) - .map(|s| { - res.copy_from_slice(s); - Self::from_bits(u32::from_le_bytes(res)) - }) - .ok_or(Error::InvalidLittleEndianBuffer) - } -} - -impl LittleEndianConvert for f64 { - fn into_little_endian(self, buffer: &mut [u8]) { - buffer.copy_from_slice(&self.to_bits().to_le_bytes()); - } - - fn from_little_endian(buffer: &[u8]) -> Result { - let mut res = [0u8; 8]; - buffer - .get(0..8) - .map(|s| { - res.copy_from_slice(s); - Self::from_bits(u64::from_le_bytes(res)) - }) - .ok_or(Error::InvalidLittleEndianBuffer) - } -} - -impl LittleEndianConvert for F32 { - fn into_little_endian(self, buffer: &mut [u8]) { - (self.to_bits() as i32).into_little_endian(buffer) - } - - fn from_little_endian(buffer: &[u8]) -> Result { - i32::from_little_endian(buffer).map(|val| Self::from_bits(val as _)) - } -} - -impl LittleEndianConvert for F64 { - fn into_little_endian(self, buffer: &mut [u8]) { - (self.to_bits() as i64).into_little_endian(buffer) - } - - fn from_little_endian(buffer: &[u8]) -> Result { - i64::from_little_endian(buffer).map(|val| Self::from_bits(val as _)) - } -} - macro_rules! impl_integer_arithmetic_ops { ($type: ident) => { impl ArithmeticOps<$type> for $type {