1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
use memmapix::MmapMut;
use std::{
marker::PhantomData,
ops::{Deref, DerefMut},
ptr,
};
/// memmap backed vec-like buffer
///
/// Attention: drop() is not called on de-allocated items! (truncate, clear, replace)
///
/// mmap vec does not allocate the requested memory on creation, only when written to.
#[derive(Debug)]
pub struct MmapVec<T> {
map: MmapMut,
len: usize,
tsize: usize,
phantom: PhantomData<T>,
}
impl<T> Default for MmapVec<T> {
fn default() -> Self {
Self::new(0)
}
}
impl MmapVec<u8> {
pub fn zeroed(len: usize) -> Self {
let mut me = Self::new(len);
me.len = len;
me
}
}
impl<T> MmapVec<T> {
pub fn new(capacity: usize) -> Self {
let tsize = std::mem::size_of::<T>();
let tlen = capacity.checked_mul(tsize).expect("buffer tlen");
let map = MmapMut::map_anon(tlen).expect("anonymous map buffer");
//map.advise(rustix::mm::Advice::Random).expect("advise random access");
Self {
map,
len: 0,
tsize,
phantom: PhantomData,
}
}
pub fn clear(&mut self) {
// copy paste from Vec
let elems: *mut [T] = self as &mut [T];
// SAFETY:
// - `elems` comes directly from `as_mut_slice` and is therefore valid.
// - Setting `self.len` before calling `drop_in_place` means that,
// if an element's `Drop` impl panics, the vector's `Drop` impl will
// do nothing (leaking the rest of the elements) instead of dropping
// some twice.
unsafe {
self.len = 0;
ptr::drop_in_place(elems);
}
}
pub fn truncate(&mut self, len: usize) {
// copy paste from Vec
// This is safe because:
//
// * the slice passed to `drop_in_place` is valid; the `len > self.len`
// case avoids creating an invalid slice, and
// * the `len` of the vector is shrunk before calling `drop_in_place`,
// such that no value will be dropped twice in case `drop_in_place`
// were to panic once (if it panics twice, the program aborts).
unsafe {
// Note: It's intentional that this is `>` and not `>=`.
// Changing it to `>=` has negative performance
// implications in some cases. See #78884 for more.
if len > self.len {
return;
}
let remaining_len = self.len - len;
let s = ptr::slice_from_raw_parts_mut(self.as_mut_ptr().add(len), remaining_len);
self.len = len;
ptr::drop_in_place(s);
}
}
pub fn resize(&mut self, len: usize, value: T)
where
T: Clone,
{
if len <= self.len {
return self.truncate(len);
}
if len > self.capacity() {
panic!("New size must fit into the allocated buffer.");
}
for _ in self.len + 1..len {
self.push(value.clone());
}
self.push(value);
}
pub fn len(&self) -> usize {
self.len
}
fn capacity(&self) -> usize {
self.map.len() / self.tsize
}
pub fn push(&mut self, item: T) -> &mut T {
let pos = self.len;
self.len += 1;
self[pos] = item;
&mut self[pos]
}
}
impl<T> Deref for MmapVec<T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
let tlen = self.len.checked_mul(self.tsize).expect("buffer len");
let mapslice = &self.map[0..tlen];
let (prefix, slice, suffix) = unsafe {
// it is safe because we always align to T size
// and we track occupied space with len
// and no one else has access to the map
mapslice.align_to::<T>()
};
debug_assert_eq!(prefix.len(), 0);
debug_assert_eq!(suffix.len(), 0);
slice
}
}
impl<T> DerefMut for MmapVec<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
let tlen = self.len.checked_mul(self.tsize).expect("buffer len");
let mapslice = &mut self.map[0..tlen];
let (prefix, slice, suffix) = unsafe {
// it is safe because we always align to T size
// and we track occupied space with len
// and no one else has access to the map
mapslice.align_to_mut::<T>()
};
debug_assert_eq!(prefix.len(), 0);
debug_assert_eq!(suffix.len(), 0);
slice
}
}
#[test]
fn test_vec() {
let mut sut = MmapVec::new(1);
sut.push(b"CDE".to_owned());
let buf = &sut.map[..];
assert_eq!(buf, b"CDE");
}