1use std::{error::Error, fs::{File, OpenOptions}, ops::{Index, IndexMut}, path::PathBuf};
2
3use memmap2::MmapMut;
4
5type HandleResult<T> = Result<T, Box<dyn Error>>;
6
7pub enum StartStorage {
8 InMemory(Vec<u8>),
9 Mapped {
10 path: PathBuf,
11 mmap: MmapMut
12 }
13}
14
15impl StartStorage {
16 pub fn len(&self) -> usize {
17 match self {
18 StartStorage::InMemory(vec) => vec.len(),
19 StartStorage::Mapped { mmap, .. } => mmap.len(),
20 }
21 }
22
23 pub fn resize(&mut self, new_len: usize) -> HandleResult<()> {
24 match self {
25 StartStorage::InMemory(vec) => {
26 vec.resize(new_len, 0);
27 },
28 StartStorage::Mapped { mmap, path } => {
29 let file = OpenOptions::new()
30 .read(true)
31 .write(true)
32 .create(true)
33 .open(&path)?;
34 file.set_len(new_len as u64)?;
35
36 let new_mmap = unsafe { MmapMut::map_mut(&file) }?;
37 *mmap = new_mmap;
38 },
39 }
40 Ok(())
41 }
42
43 pub fn in_memory() -> Self {
44 Self::InMemory(vec![])
45 }
46
47 pub fn embedded(path: PathBuf) -> HandleResult<Self> {
48 let file = OpenOptions::new()
49 .read(true)
50 .write(true)
51 .create(true)
52 .open(&path)?;
53 let mmap = unsafe { MmapMut::map_mut(&file) }?;
54 Ok(Self::Mapped { path, mmap })
55 }
56}
57
58impl Index<std::ops::Range<usize>> for StartStorage {
59 type Output = [u8];
60
61 fn index(&self, range: std::ops::Range<usize>) -> &Self::Output {
62 match &self {
63 StartStorage::InMemory(vec) => &vec[range],
64 StartStorage::Mapped{ path: _, mmap } => &mmap[range],
65 }
66 }
67}
68
69impl IndexMut<std::ops::Range<usize>> for StartStorage {
70 fn index_mut(&mut self, range: std::ops::Range<usize>) -> &mut Self::Output {
71 match self {
72 StartStorage::InMemory(vec) => &mut vec[range],
73 StartStorage::Mapped { mmap, .. } => &mut mmap[range],
74 }
75 }
76}