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.
15    _mmap: Mmap,
16    /// The raw bytes of the index data.
17    data: Vec<u8>,
18}
19
20impl MmapIndex {
21    /// Open an index file with memory mapping.
22    ///
23    /// The file is mapped read-only into memory, allowing the OS to
24    /// manage paging efficiently.
25    pub fn open(path: &Path) -> Result<Self, IndexError> {
26        let file = std::fs::File::open(path)?;
27
28        // Safety: the file is opened read-only and we don't modify the mapping
29        let mmap = unsafe { Mmap::map(&file)? };
30
31        let data = mmap.to_vec(); // Copy for now; in production, use mmap directly
32
33        Ok(Self { _mmap: mmap, data })
34    }
35
36    /// Get the raw bytes of the mapped index.
37    pub fn as_bytes(&self) -> &[u8] {
38        &self.data
39    }
40
41    /// Get the size of the mapped data.
42    pub fn len(&self) -> usize {
43        self.data.len()
44    }
45
46    /// Check if the mapped data is empty.
47    pub fn is_empty(&self) -> bool {
48        self.data.is_empty()
49    }
50}
51
52impl std::fmt::Debug for MmapIndex {
53    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54        f.debug_struct("MmapIndex")
55            .field("len", &self.data.len())
56            .finish()
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    #[test]
65    fn test_mmap_open_nonexistent() {
66        let result = MmapIndex::open(Path::new("/nonexistent/path/index.dat"));
67        assert!(result.is_err());
68    }
69
70    #[test]
71    fn test_mmap_open_existing() {
72        let dir = tempfile::tempdir().unwrap();
73        let file_path = dir.path().join("test.dat");
74        std::fs::write(&file_path, b"hello world").unwrap();
75
76        let mmap = MmapIndex::open(&file_path).unwrap();
77        assert_eq!(mmap.len(), 11);
78        assert_eq!(mmap.as_bytes(), b"hello world");
79    }
80}