mmap_storage/
anonim.rs

1//!Anonymous memory mapped storage.
2use core::cmp;
3use std::io;
4
5/// Anonymous memory map backed storage
6///
7/// It provides byte storage over anonymous memory map.
8///
9/// When new data is written the storage may be extended
10/// using following strategy:
11///
12/// - If new data is small enough, resize to double size.
13/// - Otherwise resize to new data_size.
14///
15/// If needed you can use `resize` method to shrink or extend storage.
16///
17/// Unless otherwise stated all methods that modify content of storage doesn't perform
18/// flushes, it is callee's responsibility to call it when required
19pub struct Storage {
20    inner: memmap::MmapMut,
21    //Total size of storage
22    size: usize,
23    //Cursor pointing to end of storage
24    end: usize,
25}
26
27impl Storage {
28    /// Creates storage with specified size.
29    pub fn new(size: usize) -> io::Result<Self> {
30        let inner = memmap::MmapOptions::new().len(size).map_anon()?;
31
32        Ok(Self {
33            inner,
34            end: 0,
35            size
36        })
37    }
38
39    #[inline]
40    /// Returns slice with view on written data.
41    pub fn as_slice(&self) -> &[u8] {
42        &self.inner[..self.end]
43    }
44
45    #[inline]
46    /// Returns slice with view on written data.
47    pub fn as_mut_slice(&mut self) -> &mut [u8] {
48        &mut self.inner[..self.end]
49    }
50
51    #[inline]
52    /// Returns overall size of storage(including extra space).
53    pub fn capacity(&self) -> usize {
54        self.size
55    }
56
57    #[inline]
58    /// Asynchronously flushes outstanding memory map modifications to disk.
59    ///
60    /// This method initiates flushing modified pages to durable storage, but it will not wait for
61    /// the operation to complete before returning.
62    pub fn flush_async(&self) -> io::Result<()> {
63        self.inner.flush_async()
64    }
65
66    #[inline]
67    /// Synchronously flushes outstanding memory map modifications to disk.
68    pub fn flush_sync(&self) -> io::Result<()> {
69        self.inner.flush()
70    }
71
72    //Increases mmap size by max(old_size*2, new_size)
73    fn realloc(&mut self, new_size: usize) -> io::Result<()> {
74        let new_size = cmp::max(self.size + self.size, new_size);
75        let mut new_mmap = Self::new(new_size)?;
76        new_mmap.copy_from_slice(self.as_slice());
77        *self = new_mmap;
78        Ok(())
79    }
80
81    /// Appends data to storage
82    ///
83    /// Note that it resizes storage if needed.
84    /// Therefore error can happen.
85    pub fn extend_from_slice(&mut self, data: &[u8]) -> io::Result<()> {
86        if (self.size - self.end) < data.len() {
87            let new_size = self.end + data.len();
88            self.realloc(new_size)?;
89        }
90        self.inner[self.end..self.end+data.len()].copy_from_slice(data);
91        self.end += data.len();
92        Ok(())
93    }
94
95    /// Copies data from slice into storage.
96    ///
97    /// Function panics if data has greater len.
98    ///
99    /// **Note:** It copies data up to storage capacity.
100    pub fn copy_from_slice(&mut self, data: &[u8]) {
101        assert!(self.size >= data.len());
102        self.end = data.len();
103        self.as_mut_slice().copy_from_slice(data);
104    }
105
106    /// Resizes storage by appending or truncating.
107    ///
108    /// As it requires re-create mmap, the error is possible to happen.
109    /// In case of error, original storage is preserved.
110    ///
111    /// After successfully creating new storage, previous storage content gets copied.
112    pub fn resize(&mut self, new_size: usize) -> io::Result<()> {
113        let mut new_mmap = Self::new(new_size)?;
114        new_mmap.copy_from_slice(self.as_slice());
115        *self = new_mmap;
116        Ok(())
117    }
118
119    /// Clears content of storage.
120    ///
121    /// Note that it doesn't affect capacity in any way.
122    pub fn clear(&mut self) {
123        self.end = 0;
124    }
125
126    /// Creates `Vec` from content of storage.
127    pub fn to_vec(&self) -> Vec<u8> {
128        let mut result = Vec::with_capacity(self.end);
129        result.extend_from_slice(self.as_slice());
130        result
131    }
132}
133
134impl Default for Storage {
135    ///Creates default storage with capacity 1024
136    ///
137    ///Note that it panics on error
138    fn default() -> Self {
139        Self::new(1024).expect("To create default mmap storage")
140    }
141}
142
143impl io::Write for Storage {
144    #[inline]
145    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
146        self.extend_from_slice(buf)?;
147        Ok(buf.len())
148    }
149
150    #[inline]
151    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
152        self.extend_from_slice(buf)
153    }
154
155    #[inline]
156    fn flush(&mut self) -> io::Result<()> {
157        self.inner.flush()
158    }
159}