1use memmap2::Mmap;
6use std::fs::File;
7use std::path::Path;
8
9use crate::{CyaneaError, Result};
10
11pub struct MappedFile {
13 _file: File,
14 mmap: Mmap,
15}
16
17impl MappedFile {
18 pub fn open(path: impl AsRef<Path>) -> Result<Self> {
26 let path = path.as_ref();
27 let file = File::open(path).map_err(|e| {
28 CyaneaError::Io(std::io::Error::new(
29 e.kind(),
30 format!("{}: {}", path.display(), e),
31 ))
32 })?;
33 let mmap = unsafe { Mmap::map(&file) }?;
36 Ok(Self { _file: file, mmap })
37 }
38
39 pub fn as_bytes(&self) -> &[u8] {
41 &self.mmap
42 }
43
44 pub fn len(&self) -> usize {
46 self.mmap.len()
47 }
48
49 pub fn is_empty(&self) -> bool {
51 self.mmap.is_empty()
52 }
53}
54
55impl AsRef<[u8]> for MappedFile {
56 fn as_ref(&self) -> &[u8] {
57 self.as_bytes()
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64 use std::io::Write;
65
66 #[test]
67 fn test_mmap_roundtrip() {
68 let mut file = tempfile::NamedTempFile::new().unwrap();
69 file.write_all(b"hello mmap").unwrap();
70 file.flush().unwrap();
71
72 let mapped = MappedFile::open(file.path()).unwrap();
73 assert_eq!(mapped.as_bytes(), b"hello mmap");
74 assert_eq!(mapped.len(), 10);
75 assert!(!mapped.is_empty());
76 }
77
78 #[test]
79 fn test_mmap_not_found() {
80 let result = MappedFile::open("/nonexistent/file.txt");
81 assert!(result.is_err());
82 }
83}