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}