Skip to main content

ps_mmap/
lib.rs

1#![allow(clippy::module_name_repetitions)]
2mod error;
3mod guards;
4mod readable;
5mod writable;
6
7#[cfg(test)]
8mod tests;
9
10use std::path::Path;
11
12pub use error::{DerefError, MapError};
13pub use guards::{ReadGuard, WriteGuard};
14pub use readable::ReadableMemoryMap;
15pub use writable::WritableMemoryMap;
16
17#[derive(Clone, Debug)]
18pub enum MemoryMap {
19    Readable(ReadableMemoryMap),
20    Writable(WritableMemoryMap),
21}
22
23impl MemoryMap {
24    /// # Errors
25    /// Returns [`MapError`] if mapping fails for any reason.
26    pub fn map<P: AsRef<Path>>(file_path: P, readonly: bool) -> Result<Self, MapError> {
27        if readonly {
28            Self::map_readable(file_path)
29        } else {
30            Self::map_writable(file_path)
31        }
32    }
33
34    /// # Errors
35    /// Returns [`MapError`] if mapping fails for any reason.
36    pub fn map_readable<P: AsRef<Path>>(file_path: P) -> Result<Self, MapError> {
37        Ok(Self::Readable(ReadableMemoryMap::map_path(file_path)?))
38    }
39
40    /// # Errors
41    /// Returns [`MapError`] if mapping fails for any reason.
42    pub fn map_writable<P: AsRef<Path>>(file_path: P) -> Result<Self, MapError> {
43        Ok(Self::Writable(WritableMemoryMap::map_path(file_path)?))
44    }
45
46    #[must_use]
47    pub fn read(&self) -> ReadGuard {
48        self.into()
49    }
50
51    #[must_use]
52    pub fn into_read(self) -> ReadGuard {
53        self.into()
54    }
55
56    /// # Errors
57    /// - Returns `ReadOnly` if memory map is read-only.
58    pub fn try_write(&self) -> Result<WriteGuard, DerefError> {
59        self.try_into()
60    }
61
62    /// # Errors
63    /// - Returns `ReadOnly` if memory map is read-only.
64    pub fn try_into_write(self) -> Result<WriteGuard, DerefError> {
65        self.try_into()
66    }
67
68    pub fn read_with<F, R>(&self, closure: F) -> R
69    where
70        F: FnOnce(&[u8]) -> R,
71    {
72        match self {
73            Self::Readable(mmap) => closure(mmap),
74            Self::Writable(mmap) => closure(&mmap.read()),
75        }
76    }
77
78    /// # Errors
79    /// - Returns `ReadOnly` if memory map is read-only.
80    pub fn try_write_with<F, R>(&self, closure: F) -> Result<R, DerefError>
81    where
82        F: FnOnce(&mut [u8]) -> R,
83    {
84        match self {
85            Self::Readable(_) => Err(DerefError::ReadOnly),
86            Self::Writable(mmap) => Ok(closure(&mut mmap.write())),
87        }
88    }
89
90    /// Returns a raw const pointer to the start of the mapped region.
91    ///
92    /// The pointer is valid only while the underlying mapping remains alive.
93    /// Dereferencing this pointer is always `unsafe`, and callers must ensure
94    /// synchronization when concurrent mutable access is possible.
95    #[must_use]
96    pub fn as_ptr(&self) -> *const u8 {
97        match self {
98            Self::Readable(value) => value.as_ptr(),
99            Self::Writable(value) => value.as_ptr(),
100        }
101    }
102
103    /// # Errors
104    /// - Returns `ReadOnly` if memory map is read-only.
105    ///
106    /// On success, returns a raw mutable pointer to the start of the mapped
107    /// region. The pointer is valid only while the underlying mapping remains
108    /// alive. No synchronization guard is held after returning; callers must
109    /// enforce exclusive/synchronized access before dereferencing.
110    pub fn try_as_mut_ptr(&self) -> Result<*mut u8, DerefError> {
111        match self {
112            Self::Readable(_) => Err(DerefError::ReadOnly),
113            Self::Writable(value) => Ok(value.as_mut_ptr()),
114        }
115    }
116
117    #[must_use]
118    pub fn len(&self) -> usize {
119        match self {
120            Self::Readable(value) => value.len(),
121            Self::Writable(value) => value.len(),
122        }
123    }
124
125    #[must_use]
126    pub fn is_empty(&self) -> bool {
127        self.len() == 0
128    }
129}