use std::path::Path;
#[cfg(feature="mmap")]
use {memmap2::Mmap, anyhow::Context, std::fs::File};
pub trait MemoryMap {
fn bytes(&self) -> &[u8];
}
#[cfg(feature="mmap")]
pub struct UnsafeMemoryMap {
mmap: Mmap,
}
pub struct SafeMemoryMap {
mmap: Vec<u8>,
}
#[cfg(feature="mmap")]
impl UnsafeMemoryMap {
pub fn new<P: AsRef<Path>>(path: P) -> anyhow::Result<Self> {
let path = path.as_ref();
let file = File::open(path)
.with_context(|| format!("Unable to open {path:?}"))?;
let mmap = unsafe { Mmap::map(&file)? };
Ok(Self {
mmap
})
}
}
#[cfg(feature="mmap")]
impl MemoryMap for UnsafeMemoryMap {
fn bytes(&self) -> &[u8] {
self.mmap.as_ref()
}
}
impl SafeMemoryMap {
pub fn from_file<P: AsRef<Path>>(path: P) -> anyhow::Result<Self> {
let path = path.as_ref();
let string = std::fs::read_to_string(path)?;
Ok(Self::from_string(string))
}
pub fn from_str<S : AsRef<[u8]>>(value: S) -> Self {
let mmap = value.as_ref();
let mut i = mmap.len();
while i > 0 && mmap[i-1] == b'\n' {
i -= 1;
}
let mmap = mmap[0..i].to_vec();
Self {
mmap
}
}
pub fn from_string(value: String) -> Self {
let mut mmap = value.into_bytes();
let mut i = mmap.len();
while i > 0 && mmap[i-1] == b'\n' {
i -= 1;
}
mmap.truncate(i);
Self {
mmap
}
}
}
impl MemoryMap for SafeMemoryMap {
fn bytes(&self) -> &[u8] {
self.mmap.as_ref()
}
}