mmap_wrapper/
memmap2.rs

1use core::mem::transmute_copy;
2use memmap2::{Mmap, MmapMut};
3use std::{marker::PhantomData, sync::Arc};
4
5/// A wrapper wrapper for a memory-mapped file with data of type `T`.
6///
7/// # Safety
8///
9/// `T` must have a consistent memory layout to ensure that the data is casted correctly.
10///
11/// Use `#[repr(transparent)]` if `T` is a newtype wrapper around a single field otherwise `#[repr(C)]`.
12///
13/// # Example
14/// ```rust
15/// use mmap_wrapper::MmapWrapper;
16///
17/// #[repr(C)]
18/// struct MyStruct {
19///    thing1: i32,
20///    thing2: f64,
21/// }
22///
23/// let f = std::fs::File::options()
24///     .read(true)
25///     .write(true)
26///     .create(true)
27///     .truncate(false)
28///     .open("/tmp/mystruct-mmap-test.bin")
29///     .unwrap();
30///
31/// let _ = f.set_len(std::mem::size_of::<MyStruct>() as u64);
32///
33/// let m = unsafe {
34///     memmap2::Mmap::map(&f).unwrap()
35/// };
36///
37/// let m_wrapper = MmapWrapper::<MyStruct>::new(m);
38/// let mmap_backed_mystruct = unsafe {
39///    m_wrapper.get_inner()
40/// };
41/// ```
42pub struct MmapWrapper<T> {
43    raw: Arc<Mmap>,
44    _inner: PhantomData<T>,
45}
46
47impl<T> Clone for MmapWrapper<T> {
48    fn clone(&self) -> Self {
49        MmapWrapper {
50            raw: self.raw.clone(),
51            _inner: PhantomData,
52        }
53    }
54}
55
56/// A mutable wrapper wrapper for a memory-mapped file with data of type `T`.
57///
58/// # Safety
59///
60/// `T` must have a consistent memory layout to ensure that the data is casted correctly.
61///
62/// Use `#[repr(transparent)]` if `T` is a newtype wrapper around a single field otherwise `#[repr(C)]`.
63///
64/// # Example
65/// ```rust
66/// use mmap_wrapper::MmapWrapper;
67///
68/// #[repr(C)]
69/// struct MyStruct {
70///    thing1: i32,
71///    thing2: f64,
72/// }
73///
74/// let f = std::fs::File::options()
75///     .read(true)
76///     .write(true)
77///     .create(true)
78///     .truncate(false)
79///     .open("/tmp/mystruct-mmap-test.bin")
80///     .unwrap();
81///
82/// let _ = f.set_len(std::mem::size_of::<MyStruct>() as u64);
83///
84/// let m = unsafe {
85///     memmap2::Mmap::map(&f).unwrap()
86/// };
87///
88/// let m_wrapper = MmapWrapper::<MyStruct>::new(m);
89/// let mmap_backed_mystruct = unsafe {
90///    m_wrapper.get_inner()
91/// };
92/// ```
93pub struct MmapMutWrapper<T> {
94    raw: Arc<MmapMut>,
95    _inner: PhantomData<T>,
96}
97
98impl<T> Clone for MmapMutWrapper<T> {
99    fn clone(&self) -> Self {
100        MmapMutWrapper {
101            raw: self.raw.clone(),
102            _inner: PhantomData,
103        }
104    }
105}
106
107impl<T> From<Mmap> for MmapWrapper<T> {
108    fn from(m: Mmap) -> MmapWrapper<T> {
109        MmapWrapper::new(m)
110    }
111}
112
113impl<T> From<MmapMut> for MmapMutWrapper<T> {
114    fn from(m: MmapMut) -> MmapMutWrapper<T> {
115        unsafe { MmapMutWrapper::new(m) }
116    }
117}
118
119impl<T> MmapWrapper<T> {
120    /// # Safety
121    /// the backing mmap pointer must point to valid
122    /// memory for type T [T likely has to be repr(C)]
123    pub fn new(m: Mmap) -> MmapWrapper<T> {
124        // check that size of m matches
125        // size of inner type
126        MmapWrapper {
127            raw: Arc::new(m),
128            _inner: PhantomData,
129        }
130    }
131
132    pub fn get_inner<'a>(&self) -> &'a T {
133        unsafe { &*self.raw.as_ptr().cast::<T>() }
134    }
135}
136
137impl<T> MmapMutWrapper<T> {
138    /// # Safety
139    /// the backing mmap pointer must point to valid
140    /// memory for type T [T likely has to be repr(C)]
141    pub unsafe fn new(m: MmapMut) -> MmapMutWrapper<T> {
142        MmapMutWrapper {
143            raw: Arc::new(m),
144            _inner: PhantomData,
145        }
146    }
147
148    pub fn get_inner<'a>(&mut self) -> &'a mut T {
149        unsafe { &mut *self.raw.as_ptr().cast_mut().cast::<T>() }
150    }
151}
152
153#[cfg(test)]
154mod tests {
155
156    struct TestStruct {
157        _thing1: i32,
158    }
159
160    use std::{
161        fs::{self, File},
162        thread,
163    };
164
165    use crate::MmapMutWrapper;
166
167    #[test]
168    fn arc_thread_test() {
169        let f = File::create_new("arc_thread_test").unwrap();
170        f.set_len(size_of::<TestStruct>().try_into().unwrap())
171            .unwrap();
172        let m = unsafe { memmap2::MmapMut::map_mut(&f).unwrap() };
173        let m: MmapMutWrapper<TestStruct> = unsafe { MmapMutWrapper::new(m) };
174
175        let m_clone = m.clone();
176
177        let t = thread::spawn(move || {
178            let _ = m_clone;
179        });
180
181        let _ = t.join();
182
183        drop(m);
184
185        fs::remove_file("arc_thread_test").unwrap();
186    }
187}