use memmap2::MmapMut;
use parking_lot::RwLock;
use crate::errors::{MmapIoError, Result};
use crate::mmap::{MappedSlice, MappedSliceMut};
use crate::utils::slice_range;
const ERR_ZERO_SIZE: &str = "Size must be greater than zero";
#[cfg(target_pointer_width = "64")]
const MAX_MMAP_SIZE: u64 = 128 * (1 << 40);
#[cfg(target_pointer_width = "32")]
const MAX_MMAP_SIZE: u64 = 2 * (1 << 30);
pub struct AnonymousMmap {
map: RwLock<MmapMut>,
len: u64,
}
impl AnonymousMmap {
pub fn new(size: u64) -> Result<Self> {
if size == 0 {
return Err(MmapIoError::ResizeFailed(ERR_ZERO_SIZE.into()));
}
if size > MAX_MMAP_SIZE {
return Err(MmapIoError::ResizeFailed(format!(
"Size {size} exceeds maximum safe limit of {MAX_MMAP_SIZE} bytes"
)));
}
let len_usize = usize::try_from(size)
.map_err(|_| MmapIoError::ResizeFailed(format!("Size {size} does not fit in usize")))?;
let mmap = MmapMut::map_anon(len_usize)?;
Ok(Self {
map: RwLock::new(mmap),
len: size,
})
}
#[must_use]
pub fn len(&self) -> u64 {
self.len
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn read_into(&self, offset: u64, buf: &mut [u8]) -> Result<()> {
let (start, end) = slice_range(offset, buf.len() as u64, self.len)?;
let guard = self.map.read();
buf.copy_from_slice(&guard[start..end]);
Ok(())
}
pub fn update_region(&self, offset: u64, data: &[u8]) -> Result<()> {
let (start, end) = slice_range(offset, data.len() as u64, self.len)?;
let mut guard = self.map.write();
guard[start..end].copy_from_slice(data);
Ok(())
}
pub fn as_slice(&self, offset: u64, len: u64) -> Result<MappedSlice<'_>> {
let (start, end) = slice_range(offset, len, self.len)?;
let guard = self.map.read();
Ok(MappedSlice::guarded(guard, start..end))
}
pub fn as_mut_slice(&self, offset: u64, len: u64) -> Result<MappedSliceMut<'_>> {
let (start, end) = slice_range(offset, len, self.len)?;
let guard = self.map.write();
Ok(MappedSliceMut::guarded(guard, start..end))
}
#[must_use]
pub unsafe fn as_ptr(&self) -> *const u8 {
let guard = self.map.read();
guard.as_ptr()
}
#[must_use]
pub unsafe fn as_mut_ptr(&self) -> *mut u8 {
let mut guard = self.map.write();
guard.as_mut_ptr()
}
}
impl std::fmt::Debug for AnonymousMmap {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AnonymousMmap")
.field("len", &self.len)
.finish()
}
}