Skip to main content

seekr_code/index/
mmap_store.rs

1//! Memory-mapped index storage.
2//!
3//! Uses `memmap2` for zero-copy read-only loading of index files,
4//! reducing memory usage and improving load times for large indices.
5
6use std::path::Path;
7
8use memmap2::Mmap;
9
10use crate::error::IndexError;
11
12/// A memory-mapped index file for read-only access.
13pub struct MmapIndex {
14    /// The memory-mapped file — data is accessed directly via the mmap.
15    mmap: Mmap,
16}
17
18impl MmapIndex {
19    /// Open an index file with memory mapping.
20    ///
21    /// The file is mapped read-only into memory, allowing the OS to
22    /// manage paging efficiently. No data copy is made.
23    pub fn open(path: &Path) -> Result<Self, IndexError> {
24        let file = std::fs::File::open(path)?;
25
26        // Safety: the file is opened read-only and we don't modify the mapping
27        let mmap = unsafe { Mmap::map(&file)? };
28
29        Ok(Self { mmap })
30    }
31
32    /// Get the raw bytes of the mapped index (zero-copy).
33    pub fn as_bytes(&self) -> &[u8] {
34        &self.mmap
35    }
36
37    /// Get the size of the mapped data.
38    pub fn len(&self) -> usize {
39        self.mmap.len()
40    }
41
42    /// Check if the mapped data is empty.
43    pub fn is_empty(&self) -> bool {
44        self.mmap.is_empty()
45    }
46}
47
48impl std::fmt::Debug for MmapIndex {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        f.debug_struct("MmapIndex")
51            .field("len", &self.mmap.len())
52            .finish()
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59
60    #[test]
61    fn test_mmap_open_nonexistent() {
62        let result = MmapIndex::open(Path::new("/nonexistent/path/index.dat"));
63        assert!(result.is_err());
64    }
65
66    #[test]
67    fn test_mmap_open_existing() {
68        let dir = tempfile::tempdir().unwrap();
69        let file_path = dir.path().join("test.dat");
70        std::fs::write(&file_path, b"hello world").unwrap();
71
72        let mmap = MmapIndex::open(&file_path).unwrap();
73        assert_eq!(mmap.len(), 11);
74        assert_eq!(mmap.as_bytes(), b"hello world");
75    }
76}