rustc_data_structures/
memmap.rs

1use std::fs::File;
2use std::io;
3use std::ops::{Deref, DerefMut};
4
5/// A trivial wrapper for [`memmap2::Mmap`] (or `Vec<u8>` on WASM).
6#[cfg(not(any(miri, target_arch = "wasm32")))]
7pub struct Mmap(memmap2::Mmap);
8
9#[cfg(any(miri, target_arch = "wasm32"))]
10pub struct Mmap(Vec<u8>);
11
12#[cfg(not(any(miri, target_arch = "wasm32")))]
13impl Mmap {
14    /// # Safety
15    ///
16    /// The given file must not be mutated (i.e., not written, not truncated, ...) until the mapping is closed.
17    ///
18    /// However in practice most callers do not ensure this, so uses of this function are likely unsound.
19    #[inline]
20    pub unsafe fn map(file: File) -> io::Result<Self> {
21        // By default, memmap2 creates shared mappings, implying that we could see updates to the
22        // file through the mapping. That would violate our precondition; so by requesting a
23        // map_copy_read_only we do not lose anything.
24        // This mapping mode also improves our support for filesystems such as cacheless virtiofs.
25        // For more details see https://github.com/rust-lang/rust/issues/122262
26        //
27        // SAFETY: The caller must ensure that this is safe.
28        unsafe { memmap2::MmapOptions::new().map_copy_read_only(&file).map(Mmap) }
29    }
30}
31
32#[cfg(any(miri, target_arch = "wasm32"))]
33impl Mmap {
34    #[inline]
35    pub unsafe fn map(mut file: File) -> io::Result<Self> {
36        use std::io::Read;
37
38        let mut data = Vec::new();
39        file.read_to_end(&mut data)?;
40        Ok(Mmap(data))
41    }
42}
43
44impl Deref for Mmap {
45    type Target = [u8];
46
47    #[inline]
48    fn deref(&self) -> &[u8] {
49        &self.0
50    }
51}
52
53impl AsRef<[u8]> for Mmap {
54    fn as_ref(&self) -> &[u8] {
55        &self.0
56    }
57}
58
59#[cfg(not(any(miri, target_arch = "wasm32")))]
60pub struct MmapMut(memmap2::MmapMut);
61
62#[cfg(any(miri, target_arch = "wasm32"))]
63pub struct MmapMut(Vec<u8>);
64
65#[cfg(not(any(miri, target_arch = "wasm32")))]
66impl MmapMut {
67    #[inline]
68    pub fn map_anon(len: usize) -> io::Result<Self> {
69        let mmap = memmap2::MmapMut::map_anon(len)?;
70        Ok(MmapMut(mmap))
71    }
72
73    #[inline]
74    pub fn flush(&mut self) -> io::Result<()> {
75        self.0.flush()
76    }
77
78    #[inline]
79    pub fn make_read_only(self) -> std::io::Result<Mmap> {
80        let mmap = self.0.make_read_only()?;
81        Ok(Mmap(mmap))
82    }
83}
84
85#[cfg(any(miri, target_arch = "wasm32"))]
86impl MmapMut {
87    #[inline]
88    pub fn map_anon(len: usize) -> io::Result<Self> {
89        let data = Vec::with_capacity(len);
90        Ok(MmapMut(data))
91    }
92
93    #[inline]
94    pub fn flush(&mut self) -> io::Result<()> {
95        Ok(())
96    }
97
98    #[inline]
99    pub fn make_read_only(self) -> std::io::Result<Mmap> {
100        Ok(Mmap(self.0))
101    }
102}
103
104impl Deref for MmapMut {
105    type Target = [u8];
106
107    #[inline]
108    fn deref(&self) -> &[u8] {
109        &self.0
110    }
111}
112
113impl DerefMut for MmapMut {
114    #[inline]
115    fn deref_mut(&mut self) -> &mut [u8] {
116        &mut self.0
117    }
118}