| use std::fs::File; | |
| use std::io; | |
| use std::ops::{Deref, DerefMut}; | |
| /// A trivial wrapper for [`memmap2::Mmap`] (or `Vec<u8>` on WASM). | |
| #[cfg(not(any(miri, target_arch = "wasm32")))] | |
| pub struct Mmap(memmap2::Mmap); | |
| #[cfg(any(miri, target_arch = "wasm32"))] | |
| pub struct Mmap(Vec<u8>); | |
| #[cfg(not(any(miri, target_arch = "wasm32")))] | |
| impl Mmap { | |
| /// # Safety | |
| /// | |
| /// The given file must not be mutated (i.e., not written, not truncated, ...) until the mapping is closed. | |
| /// | |
| /// However in practice most callers do not ensure this, so uses of this function are likely unsound. | |
| #[inline] | |
| pub unsafe fn map(file: File) -> io::Result<Self> { | |
| // By default, memmap2 creates shared mappings, implying that we could see updates to the | |
| // file through the mapping. That would violate our precondition; so by requesting a | |
| // map_copy_read_only we do not lose anything. | |
| // This mapping mode also improves our support for filesystems such as cacheless virtiofs. | |
| // For more details see https://github.com/rust-lang/rust/issues/122262 | |
| // | |
| // SAFETY: The caller must ensure that this is safe. | |
| unsafe { memmap2::MmapOptions::new().map_copy_read_only(&file).map(Mmap) } | |
| } | |
| } | |
| #[cfg(any(miri, target_arch = "wasm32"))] | |
| impl Mmap { | |
| #[inline] | |
| pub unsafe fn map(mut file: File) -> io::Result<Self> { | |
| use std::io::Read; | |
| let mut data = Vec::new(); | |
| file.read_to_end(&mut data)?; | |
| Ok(Mmap(data)) | |
| } | |
| } | |
| impl Deref for Mmap { | |
| type Target = [u8]; | |
| #[inline] | |
| fn deref(&self) -> &[u8] { | |
| &self.0 | |
| } | |
| } | |
| impl AsRef<[u8]> for Mmap { | |
| fn as_ref(&self) -> &[u8] { | |
| &self.0 | |
| } | |
| } | |
| #[cfg(not(any(miri, target_arch = "wasm32")))] | |
| pub struct MmapMut(memmap2::MmapMut); | |
| #[cfg(any(miri, target_arch = "wasm32"))] | |
| pub struct MmapMut(Vec<u8>); | |
| #[cfg(not(any(miri, target_arch = "wasm32")))] | |
| impl MmapMut { | |
| #[inline] | |
| pub fn map_anon(len: usize) -> io::Result<Self> { | |
| let mmap = memmap2::MmapMut::map_anon(len)?; | |
| Ok(MmapMut(mmap)) | |
| } | |
| #[inline] | |
| pub fn flush(&mut self) -> io::Result<()> { | |
| self.0.flush() | |
| } | |
| #[inline] | |
| pub fn make_read_only(self) -> std::io::Result<Mmap> { | |
| let mmap = self.0.make_read_only()?; | |
| Ok(Mmap(mmap)) | |
| } | |
| } | |
| #[cfg(any(miri, target_arch = "wasm32"))] | |
| impl MmapMut { | |
| #[inline] | |
| pub fn map_anon(len: usize) -> io::Result<Self> { | |
| let data = Vec::with_capacity(len); | |
| Ok(MmapMut(data)) | |
| } | |
| #[inline] | |
| pub fn flush(&mut self) -> io::Result<()> { | |
| Ok(()) | |
| } | |
| #[inline] | |
| pub fn make_read_only(self) -> std::io::Result<Mmap> { | |
| Ok(Mmap(self.0)) | |
| } | |
| } | |
| impl Deref for MmapMut { | |
| type Target = [u8]; | |
| #[inline] | |
| fn deref(&self) -> &[u8] { | |
| &self.0 | |
| } | |
| } | |
| impl DerefMut for MmapMut { | |
| #[inline] | |
| fn deref_mut(&mut self) -> &mut [u8] { | |
| &mut self.0 | |
| } | |
| } |