use anyhow::{anyhow, Result};
pub struct Mmap(&'static [u8]);
pub struct MmapMut(&'static mut [u8]);
pub struct MmapOptions {
size: usize,
}
impl MmapOptions {
pub fn page_size() -> usize {
64 * 1024
}
pub fn new(size: usize) -> Result<Self> {
let page_size = Self::page_size();
if size % page_size != 0 {
return Err(anyhow!("Size must be a multiple of the page size"));
}
Ok(Self { size })
}
pub fn map(&self) -> Result<Mmap> {
Mmap::new(self.size)
}
}
impl Mmap {
pub unsafe fn from_raw_parts(ptr: *const u8, size: usize) -> Result<Mmap> {
if ptr.is_null() {
return Err(anyhow!("Pointer is null"));
}
Ok(Mmap(std::slice::from_raw_parts(ptr, size)))
}
pub fn new(size: usize) -> Result<Mmap> {
let page_size = MmapOptions::page_size();
let ptr = unsafe {
std::alloc::alloc(std::alloc::Layout::from_size_align(size, page_size).unwrap())
};
if ptr.is_null() {
return Err(anyhow!("Failed to allocate memory"));
}
Ok(Mmap(unsafe { std::slice::from_raw_parts(ptr, size) }))
}
pub fn as_ptr(&self) -> *const u8 {
self.0.as_ptr()
}
pub fn make_mut(self) -> Result<MmapMut> {
unsafe { MmapMut::from_raw_parts(self.0.as_ptr() as *mut u8, self.0.len()) }
}
pub fn make_exec(self) -> Result<Mmap> {
Ok(self)
}
pub fn split_to(&mut self, offset: usize) -> Result<Mmap> {
if offset > self.0.len() {
return Err(anyhow!("Offset is out of bounds"));
}
let (left, right) = self.0.split_at(offset);
self.0 = left;
Ok(Mmap(right))
}
}
impl MmapMut {
pub unsafe fn from_raw_parts(ptr: *mut u8, size: usize) -> Result<MmapMut> {
if ptr.is_null() {
return Err(anyhow!("Pointer is null"));
}
Ok(MmapMut(std::slice::from_raw_parts_mut(ptr, size)))
}
pub fn as_mut_ptr(&mut self) -> *mut u8 {
self.0.as_mut_ptr()
}
pub fn as_ptr(&self) -> *const u8 {
self.0.as_ptr()
}
pub fn as_mut_slice(&mut self) -> &mut [u8] {
self.0
}
pub fn make_read_only(self) -> Result<Mmap> {
unsafe { Mmap::from_raw_parts(self.0.as_ptr(), self.0.len()) }
}
}