use std::{mem::MaybeUninit, ops::Range};
use wasmer_types::Pages;
use crate::{
AsStoreRef, Memory, MemoryAccessError,
buffer::{BackendMemoryBuffer, MemoryBuffer},
macros::backend::{gen_rt_ty, match_rt},
};
gen_rt_ty! {
#[derive(Debug, derive_more::From)]
pub BackendMemoryView<'a>(entities::memory::view::MemoryView<'a>);
}
impl<'a> BackendMemoryView<'a> {
#[inline]
#[allow(clippy::needless_return)]
pub(crate) fn new(memory: &Memory, store: &'a (impl AsStoreRef + ?Sized)) -> Self {
match &store.as_store_ref().inner.store {
#[cfg(feature = "sys")]
crate::BackendStore::Sys(s) => Self::Sys(
crate::backend::sys::entities::memory::view::MemoryView::new(
memory.as_sys(),
store,
),
),
#[cfg(feature = "v8")]
crate::BackendStore::V8(s) => Self::V8(
crate::backend::v8::entities::memory::view::MemoryView::new(memory.as_v8(), store),
),
#[cfg(feature = "js")]
crate::BackendStore::Js(s) => Self::Js(
crate::backend::js::entities::memory::view::MemoryView::new(memory.as_js(), store),
),
}
}
#[doc(hidden)]
#[inline]
pub fn data_ptr(&self) -> *mut u8 {
match_rt!(on self => s {
s.data_ptr()
})
}
#[inline]
pub fn data_size(&self) -> u64 {
match_rt!(on self => s {
s.data_size()
})
}
#[doc(hidden)]
#[inline]
pub unsafe fn data_unchecked(&self) -> &[u8] {
match_rt!(on self => s {
unsafe { s.data_unchecked() }
})
}
#[allow(clippy::mut_from_ref)]
#[doc(hidden)]
#[inline]
pub unsafe fn data_unchecked_mut(&self) -> &mut [u8] {
match_rt!(on self => s {
unsafe { s.data_unchecked_mut() }
})
}
#[inline]
pub fn size(&self) -> Pages {
match_rt!(on self => s {
s.size()
})
}
#[inline]
pub(crate) fn buffer(&'a self) -> MemoryBuffer<'a> {
match self {
#[cfg(feature = "sys")]
Self::Sys(s) => MemoryBuffer(BackendMemoryBuffer::Sys(s.buffer())),
#[cfg(feature = "v8")]
Self::V8(s) => MemoryBuffer(BackendMemoryBuffer::V8(s.buffer())),
#[cfg(feature = "js")]
Self::Js(s) => MemoryBuffer(BackendMemoryBuffer::Js(s.buffer())),
}
}
#[inline]
pub fn read(&self, offset: u64, buf: &mut [u8]) -> Result<(), MemoryAccessError> {
match_rt!(on self => s {
s.read(offset, buf)
})
}
#[inline]
pub fn read_u8(&self, offset: u64) -> Result<u8, MemoryAccessError> {
match_rt!(on self => s {
s.read_u8(offset)
})
}
#[inline]
pub fn read_uninit<'b>(
&self,
offset: u64,
buf: &'b mut [MaybeUninit<u8>],
) -> Result<&'b mut [u8], MemoryAccessError> {
match_rt!(on self => s {
s.read_uninit(offset, buf)
})
}
#[inline]
pub fn write(&self, offset: u64, data: &[u8]) -> Result<(), MemoryAccessError> {
match_rt!(on self => s {
s.write(offset, data)
})
}
#[inline]
pub fn write_u8(&self, offset: u64, val: u8) -> Result<(), MemoryAccessError> {
match_rt!(on self => s {
s.write_u8(offset, val)
})
}
#[inline]
pub fn copy_to_vec(&self) -> Result<Vec<u8>, MemoryAccessError> {
self.copy_range_to_vec(0..self.data_size())
}
#[inline]
pub fn copy_range_to_vec(&self, range: Range<u64>) -> Result<Vec<u8>, MemoryAccessError> {
let mut new_memory = Vec::new();
let mut offset = range.start;
let end = range.end.min(self.data_size());
let mut chunk = [0u8; 40960];
while offset < end {
let remaining = end - offset;
let sublen = remaining.min(chunk.len() as u64) as usize;
self.read(offset, &mut chunk[..sublen])?;
new_memory.extend_from_slice(&chunk[..sublen]);
offset += sublen as u64;
}
Ok(new_memory)
}
#[inline]
pub fn copy_to_memory(&self, amount: u64, new_memory: &Self) -> Result<(), MemoryAccessError> {
let mut offset = 0;
let mut chunk = [0u8; 40960];
while offset < amount {
let remaining = amount - offset;
let sublen = remaining.min(chunk.len() as u64) as usize;
self.read(offset, &mut chunk[..sublen])?;
new_memory.write(offset, &chunk[..sublen])?;
offset += sublen as u64;
}
Ok(())
}
}