use crate::error::{Error, Result};
use crate::instance::Instance;
use fizzyx_sys as sys;
pub const PAGE_SIZE: usize = 65536;
#[derive(Debug, Copy, Clone)]
pub struct Memory {
_private: (),
}
impl Memory {
pub(crate) fn new() -> Self {
Self { _private: () }
}
pub fn size(&self, instance: &Instance) -> u64 {
(self.data_size(instance) / PAGE_SIZE) as u64
}
pub fn data_size(&self, instance: &Instance) -> usize {
unsafe { sys::fizzy_get_instance_memory_size(instance.as_ptr()) }
}
pub fn data<'a>(&self, instance: &'a Instance) -> &'a [u8] {
unsafe {
let ptr = sys::fizzy_get_instance_memory_data(instance.as_ptr());
let size = sys::fizzy_get_instance_memory_size(instance.as_ptr());
if ptr.is_null() || size == 0 {
&[]
} else {
core::slice::from_raw_parts(ptr, size)
}
}
}
pub fn data_mut<'a>(&self, instance: &'a mut Instance) -> &'a mut [u8] {
unsafe {
let ptr = sys::fizzy_get_instance_memory_data(instance.as_ptr());
let size = sys::fizzy_get_instance_memory_size(instance.as_ptr());
if ptr.is_null() || size == 0 {
&mut []
} else {
core::slice::from_raw_parts_mut(ptr, size)
}
}
}
pub fn read(&self, instance: &Instance, offset: u32, buf: &mut [u8]) -> Result<()> {
let data = self.data(instance);
let start = offset as usize;
let end = start
.checked_add(buf.len())
.filter(|&end| end <= data.len())
.ok_or(Error::MemoryOutOfBounds {
offset: start,
length: buf.len(),
size: data.len(),
})?;
buf.copy_from_slice(&data[start..end]);
Ok(())
}
pub fn write(&self, instance: &mut Instance, offset: u32, buf: &[u8]) -> Result<()> {
let data = self.data_mut(instance);
let start = offset as usize;
let end = start
.checked_add(buf.len())
.filter(|&end| end <= data.len())
.ok_or(Error::MemoryOutOfBounds {
offset: start,
length: buf.len(),
size: data.len(),
})?;
data[start..end].copy_from_slice(buf);
Ok(())
}
}