Skip to main content

mmap_guard/
file_data.rs

1//! The [`FileData`] enum — a unified read-only view over memory-mapped and
2//! heap-allocated file data.
3
4use std::fs::File;
5use std::ops::Deref;
6
7use memmap2::Mmap;
8
9/// File data backed by either a memory map or a heap buffer.
10///
11/// Both variants dereference to `&[u8]`, so consumers can treat the data
12/// uniformly regardless of the backing store.
13///
14/// # Errors
15///
16/// This type does not produce errors directly. Errors arise from the
17/// functions that construct it — see [`map_file`](crate::map_file),
18/// [`load()`](crate::load()), and [`load_stdin`](crate::load_stdin).
19///
20/// # Compatibility
21///
22/// This enum is `#[non_exhaustive]`, so match arms must include a wildcard.
23/// The `Mapped` variant carries **two** fields — the memory map and the
24/// file handle (for advisory locking). Always pattern-match with `..`
25/// (e.g., `FileData::Mapped(..)`) rather than a fixed number of fields,
26/// so your code remains forward-compatible if additional fields are added.
27///
28/// # Examples
29///
30/// ```no_run
31/// use mmap_guard::map_file;
32///
33/// let data = map_file("example.bin").unwrap();
34/// let bytes: &[u8] = &data;
35/// println!("first byte: {:#04x}", bytes[0]);
36/// ```
37#[derive(Debug)]
38#[non_exhaustive]
39pub enum FileData {
40    /// Data backed by a read-only memory map (zero-copy).
41    ///
42    /// The [`File`] handle is retained to hold the advisory lock for the
43    /// lifetime of the map. Always match with `Mapped(..)` for forward
44    /// compatibility.
45    Mapped(Mmap, File),
46    /// Data loaded into a heap-allocated buffer.
47    Loaded(Vec<u8>),
48}
49
50impl Deref for FileData {
51    type Target = [u8];
52
53    fn deref(&self) -> &[u8] {
54        match self {
55            Self::Mapped(mmap, _file) => mmap,
56            Self::Loaded(vec) => vec,
57        }
58    }
59}
60
61impl AsRef<[u8]> for FileData {
62    fn as_ref(&self) -> &[u8] {
63        self
64    }
65}
66
67// Compile-time assertions: FileData must be Send + Sync so it can be shared
68// across threads (Mmap and File are both Send + Sync).
69// LCOV_EXCL_START — compile-time only, never called at runtime
70const _: () = {
71    const fn assert_send_sync<T: Send + Sync>() {}
72    #[allow(dead_code)]
73    const fn check() {
74        assert_send_sync::<FileData>();
75    }
76};
77// LCOV_EXCL_STOP
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82
83    #[test]
84    fn loaded_variant_derefs_to_bytes() {
85        let data = FileData::Loaded(vec![0xDE, 0xAD, 0xBE, 0xEF]);
86        let bytes: &[u8] = &data;
87        assert_eq!(bytes, &[0xDE, 0xAD, 0xBE, 0xEF]);
88    }
89
90    #[test]
91    fn loaded_variant_as_ref() {
92        let data = FileData::Loaded(vec![1, 2, 3]);
93        let bytes: &[u8] = data.as_ref();
94        assert_eq!(bytes, &[1, 2, 3]);
95    }
96
97    #[test]
98    fn empty_loaded_variant() {
99        let data = FileData::Loaded(vec![]);
100        assert!(data.is_empty());
101        assert_eq!(data.len(), 0);
102    }
103}