use crate::exports::{ExportError, Exportable};
use crate::externals::Extern;
use crate::store::Store;
use crate::{MemoryType, MemoryView};
use std::convert::TryInto;
use std::slice;
use std::sync::Arc;
use wasmer_engine::{Export, ExportMemory};
use wasmer_types::{Pages, ValueType};
use wasmer_vm::{Memory as RuntimeMemory, MemoryError, VMExportMemory};
#[derive(Debug, Clone)]
pub struct Memory {
store: Store,
memory: Arc<dyn RuntimeMemory>,
}
impl Memory {
pub fn new(store: &Store, ty: MemoryType) -> Result<Self, MemoryError> {
let tunables = store.tunables();
let style = tunables.memory_style(&ty);
let memory = tunables.create_host_memory(&ty, &style)?;
Ok(Self {
store: store.clone(),
memory,
})
}
pub fn ty(&self) -> &MemoryType {
self.memory.ty()
}
pub fn store(&self) -> &Store {
&self.store
}
pub unsafe fn data_unchecked(&self) -> &[u8] {
self.data_unchecked_mut()
}
#[allow(clippy::mut_from_ref)]
pub unsafe fn data_unchecked_mut(&self) -> &mut [u8] {
let definition = self.memory.vmmemory();
let def = definition.as_ref();
slice::from_raw_parts_mut(def.base, def.current_length.try_into().unwrap())
}
pub fn data_ptr(&self) -> *mut u8 {
let definition = self.memory.vmmemory();
let def = unsafe { definition.as_ref() };
def.base
}
pub fn data_size(&self) -> u64 {
let definition = self.memory.vmmemory();
let def = unsafe { definition.as_ref() };
def.current_length.into()
}
pub fn size(&self) -> Pages {
self.memory.size()
}
pub fn grow<IntoPages>(&self, delta: IntoPages) -> Result<Pages, MemoryError>
where
IntoPages: Into<Pages>,
{
self.memory.grow(delta.into())
}
pub fn view<T: ValueType>(&self) -> MemoryView<T> {
let base = self.data_ptr();
let length = self.size().bytes().0 / std::mem::size_of::<T>();
unsafe { MemoryView::new(base as _, length as u32) }
}
pub(crate) fn from_vm_export(store: &Store, wasmer_export: ExportMemory) -> Self {
Self {
store: store.clone(),
memory: wasmer_export.vm_memory.from,
}
}
pub fn same(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.memory, &other.memory)
}
}
impl<'a> Exportable<'a> for Memory {
fn to_export(&self) -> Export {
ExportMemory {
vm_memory: VMExportMemory {
from: self.memory.clone(),
instance_ref: None,
},
}
.into()
}
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> {
match _extern {
Extern::Memory(memory) => Ok(memory),
_ => Err(ExportError::IncompatibleType),
}
}
}