use std::{fs::File, path::Path, sync::Arc};
use super::{
artifacts::tree::resolve_or,
error::{Artifact, Error, ReadFailure, Result},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum Access {
Random,
Default,
}
#[derive(Debug)]
pub(crate) struct ReadOnlyMap {
map: memmap2::Mmap,
}
impl ReadOnlyMap {
pub(crate) fn open(artifact: Artifact, path: &Path, access: Access) -> Result<Arc<Self>> {
let read = |e| Error::Read(ReadFailure::new(artifact, path.to_path_buf(), e));
match resolve_or(path, read)? {
Some(found) if found.is_file() => {}
Some(_) => return Err(read(std::io::Error::other("not a regular file"))),
None => return Err(read(std::io::ErrorKind::NotFound.into())),
}
let file = File::open(path).map_err(read)?;
let map = unsafe { memmap2::Mmap::map(&file) }.map_err(read)?;
if access == Access::Random {
map.advise(memmap2::Advice::Random).map_err(read)?;
}
Ok(Arc::new(Self { map }))
}
#[inline]
pub(crate) fn bytes(&self) -> &[u8] {
&self.map
}
}