use crate::memory::{
error::{Error, ErrorKind, Result},
primitives::PhysicalAddress,
readable::Readable,
};
use memmap2::Mmap;
use std::{fs::File, path::Path, sync::Arc};
pub struct RawSnapshot {
mmap: Mmap,
}
impl RawSnapshot {
pub fn new(file_path: &Path) -> Result<Arc<Self>> {
let file = File::open(file_path)?;
#[allow(unsafe_code)]
let mmap = unsafe { Mmap::map(&file)? };
Ok(Arc::new(RawSnapshot { mmap }))
}
}
impl Readable for RawSnapshot {
fn read(&self, buffer: &mut [u8], physical_address: PhysicalAddress) -> Result<usize> {
let offset: u64 = physical_address.into();
let start = offset as usize;
if start >= self.mmap.len() {
return Err(Error::new(
ErrorKind::IOError,
&format!("Physical address {physical_address} is outside the snapshot"),
));
}
let end = (start + buffer.len()).min(self.mmap.len());
let bytes_to_read = end - start;
if bytes_to_read > 0 {
buffer[..bytes_to_read].copy_from_slice(&self.mmap[start..end]);
}
Ok(bytes_to_read)
}
fn len(&self) -> Result<u64> {
Ok(self.mmap.len() as u64)
}
}