use std::{cell::Cell, fmt, marker::PhantomData, mem}; use wasmer_runtime_core::{ memory::Memory, types::{Type, ValueError, ValueType, WasmExternType}, }; pub struct Array; pub struct Item; #[repr(transparent)] pub struct WasmPtr { offset: u32, _phantom: PhantomData<(T, Ty)>, } impl WasmPtr { #[inline] pub fn new(offset: u32) -> Self { Self { offset, _phantom: PhantomData, } } #[inline] pub fn offset(self) -> u32 { self.offset } } impl WasmPtr { #[inline] pub fn deref<'a>(self, memory: &'a Memory) -> Option<&'a Cell> { if (self.offset as usize) + mem::size_of::() >= memory.size().bytes().0 { return None; } unsafe { let cell_ptr = memory .view::() .get_unchecked((self.offset() as usize) / mem::size_of::()) as *const _; Some(&*cell_ptr) } } } impl WasmPtr { #[inline] pub fn deref<'a>(self, memory: &'a Memory, index: u32, length: u32) -> Option<&'a [Cell]> { if (self.offset as usize) + (mem::size_of::() * ((index + length) as usize)) >= memory.size().bytes().0 { return None; } unsafe { let cell_ptrs = memory.view::().get_unchecked( ((self.offset as usize) / mem::size_of::()) + (index as usize) ..((self.offset() as usize) / mem::size_of::()) + ((index + length) as usize), ) as *const _; Some(&*cell_ptrs) } } } unsafe impl WasmExternType for WasmPtr { const TYPE: Type = Type::I32; } impl ValueType for WasmPtr { fn into_le(self, buffer: &mut [u8]) { buffer[..mem::size_of::()].copy_from_slice(&self.offset.to_le_bytes()); } fn from_le(buffer: &[u8]) -> Result { if buffer.len() >= mem::size_of::() { let mut array = [0u8; mem::size_of::()]; array.copy_from_slice(&buffer[..mem::size_of::()]); Ok(Self { offset: u32::from_le_bytes(array), _phantom: PhantomData, }) } else { Err(ValueError::BufferTooSmall) } } } impl Clone for WasmPtr { fn clone(&self) -> Self { Self { offset: self.offset, _phantom: PhantomData, } } } impl Copy for WasmPtr {} impl PartialEq for WasmPtr { fn eq(&self, other: &Self) -> bool { self.offset == other.offset } } impl Eq for WasmPtr {} impl fmt::Debug for WasmPtr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "WasmPtr({:#x})", self.offset) } }