bindb/storage/
single.rs

1use std::{fs::File, marker::PhantomData};
2use binbuf::{BytesPtr, bytes_ptr};
3use memmap2::MmapMut;
4
5#[derive(Debug)]
6pub enum OpenError {
7    Io(std::io::Error)
8}
9
10#[derive(Debug)]
11pub enum CreateError {
12    Io(std::io::Error)
13}
14
15#[derive(Debug)]
16pub enum SetError {
17    Io(std::io::Error),
18}
19
20pub enum OpenMode<T> {
21    New(T),
22    Existing,
23}
24
25pub struct Value<T> {
26    file: File,
27    mmap: MmapMut,
28    len: usize,
29    _marker: PhantomData<fn() -> T>
30}
31
32impl<T: binbuf::Dynamic> Value<T> {
33    pub unsafe fn open(mode: OpenMode<impl binbuf::dynamic::Readable<T>>, file: File) -> Result<Self, OpenError> {
34        let (len, mmap) = match mode {
35            OpenMode::New(value) => {
36                let len = value.len();
37                file.set_len(len as u64).map_err(OpenError::Io)?;
38                let mut mmap = MmapMut::map_mut(&file).map_err(OpenError::Io)?;
39                let buf = unsafe { T::buf(bytes_ptr::Mut::from_slice(&mut mmap[0 .. ])) };
40                value.write_to(buf);
41                (len, mmap)
42            },
43            OpenMode::Existing => {
44                let mut mmap = MmapMut::map_mut(&file).map_err(OpenError::Io)?;
45                let len = binbuf::dynamic::ptr_len::<T>(bytes_ptr::Const::from_slice(&mmap[0 .. ]));
46                (len, mmap)
47            }
48        };
49        Ok(Self { file, mmap, len, _marker: PhantomData })
50    }
51
52    pub fn set(&mut self, value: impl binbuf::dynamic::Readable<T>) -> Result<usize, SetError> {
53        let len = value.len();
54        if len > self.len {
55            self.file.set_len(len as u64).map_err(SetError::Io)?;
56            self.mmap = unsafe { MmapMut::map_mut(&self.file) }.map_err(SetError::Io)?;
57            self.len = len;
58        }
59        let written_len = value.write_to(self.buf_mut());
60        debug_assert_eq!(len, written_len);
61        Ok(len)
62    }
63
64    pub fn buf(&self) -> binbuf::BufConst<T> {
65        unsafe { T::buf(bytes_ptr::Const::from_slice(&self.mmap[0 .. ])) }
66    }
67
68    pub fn buf_mut(&mut self) -> binbuf::BufMut<T> {
69        unsafe { T::buf(bytes_ptr::Mut::from_slice(&mut self.mmap[0 .. ])) }
70    }
71}
72
73impl<T: binbuf::dynamic::Decode> Value<T> {
74    pub fn get(&self) -> T {
75        T::decode(self.buf()).0
76    }
77}