Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/core/src/alloc/vec.rs
3073 views
1
use crate::alloc::{TryClone, try_realloc};
2
use crate::error::OutOfMemory;
3
use core::{
4
fmt, mem,
5
ops::{Deref, DerefMut, Index, IndexMut},
6
};
7
use std_alloc::alloc::Layout;
8
use std_alloc::boxed::Box;
9
use std_alloc::vec::Vec as StdVec;
10
11
/// Like `std::vec::Vec` but all methods that allocate force handling allocation
12
/// failure.
13
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
14
pub struct Vec<T> {
15
inner: StdVec<T>,
16
}
17
18
impl<T> Default for Vec<T> {
19
fn default() -> Self {
20
Self {
21
inner: Default::default(),
22
}
23
}
24
}
25
26
impl<T: fmt::Debug> fmt::Debug for Vec<T> {
27
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28
fmt::Debug::fmt(&self.inner, f)
29
}
30
}
31
32
impl<T> TryClone for Vec<T>
33
where
34
T: TryClone,
35
{
36
fn try_clone(&self) -> Result<Self, OutOfMemory> {
37
let mut v = Vec::with_capacity(self.len())?;
38
for x in self {
39
v.push(x.try_clone()?).expect("reserved capacity");
40
}
41
Ok(v)
42
}
43
}
44
45
impl<T> Vec<T> {
46
/// Same as [`std::vec::Vec::new`].
47
pub const fn new() -> Self {
48
Self {
49
inner: StdVec::new(),
50
}
51
}
52
53
/// Same as [`std::vec::Vec::with_capacity`] but returns an error on
54
/// allocation failure.
55
pub fn with_capacity(capacity: usize) -> Result<Self, OutOfMemory> {
56
let mut v = Self::new();
57
v.reserve(capacity)?;
58
Ok(v)
59
}
60
61
/// Same as [`std::vec::Vec::reserve`] but returns an error on allocation
62
/// failure.
63
pub fn reserve(&mut self, additional: usize) -> Result<(), OutOfMemory> {
64
self.inner.try_reserve(additional).map_err(|_| {
65
OutOfMemory::new(
66
self.len()
67
.saturating_add(additional)
68
.saturating_mul(mem::size_of::<T>()),
69
)
70
})
71
}
72
73
/// Same as [`std::vec::Vec::reserve_exact`] but returns an error on allocation
74
/// failure.
75
pub fn reserve_exact(&mut self, additional: usize) -> Result<(), OutOfMemory> {
76
self.inner
77
.try_reserve_exact(additional)
78
.map_err(|_| OutOfMemory::new(self.len().saturating_add(additional)))
79
}
80
81
/// Same as [`std::vec::Vec::len`].
82
pub fn len(&self) -> usize {
83
self.inner.len()
84
}
85
86
/// Same as [`std::vec::Vec::capacity`].
87
pub fn capacity(&self) -> usize {
88
self.inner.capacity()
89
}
90
91
/// Same as [`std::vec::Vec::is_empty`].
92
pub fn is_empty(&self) -> bool {
93
self.inner.is_empty()
94
}
95
96
/// Same as [`std::vec::Vec::push`] but returns an error on allocation
97
/// failure.
98
pub fn push(&mut self, value: T) -> Result<(), OutOfMemory> {
99
self.reserve(1)?;
100
self.inner.push(value);
101
Ok(())
102
}
103
104
/// Same as [`std::vec::Vec::pop`].
105
pub fn pop(&mut self) -> Option<T> {
106
self.inner.pop()
107
}
108
109
/// Same as [`std::vec::Vec::into_raw_parts`].
110
pub fn into_raw_parts(mut self) -> (*mut T, usize, usize) {
111
// NB: Can't use `Vec::into_raw_parts` until our MSRV is >= 1.93.
112
#[cfg(not(miri))]
113
{
114
let ptr = self.as_mut_ptr();
115
let len = self.len();
116
let cap = self.capacity();
117
mem::forget(self);
118
(ptr, len, cap)
119
}
120
// NB: Miri requires using `into_raw_parts`, but always run on nightly,
121
// so it's fine to use there.
122
#[cfg(miri)]
123
{
124
let _ = &mut self;
125
self.inner.into_raw_parts()
126
}
127
}
128
129
/// Same as [`std::vec::Vec::from_raw_parts`].
130
pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self {
131
Vec {
132
// Safety: Same as our unsafe contract.
133
inner: unsafe { StdVec::from_raw_parts(ptr, length, capacity) },
134
}
135
}
136
137
/// Same as [`std::vec::Vec::drain`].
138
pub fn drain<R>(&mut self, range: R) -> std_alloc::vec::Drain<'_, T>
139
where
140
R: core::ops::RangeBounds<usize>,
141
{
142
self.inner.drain(range)
143
}
144
145
/// Same as [`std::vec::Vec::shrink_to_fit`] but returns an error on
146
/// allocation failure.
147
pub fn shrink_to_fit(&mut self) -> Result<(), OutOfMemory> {
148
// If our length is already equal to our capacity, then there is nothing
149
// to shrink.
150
if self.len() == self.capacity() {
151
return Ok(());
152
}
153
154
// `realloc` requires a non-zero original layout as well as a non-zero
155
// destination layout, so this guard ensures that the sizes below are
156
// all nonzero. This handles a few cases:
157
//
158
// * If `len == cap == 0` then no allocation has ever been made.
159
// * If `len == 0` and `cap != 0` then this function effectively frees
160
// the memory.
161
// * If `T` is a zero-sized type then nothing's been allocated either.
162
//
163
// In all of these cases delegate to the standard library's
164
// `shrink_to_fit` which is guaranteed to not perform a `realloc`.
165
if self.is_empty() || mem::size_of::<T>() == 0 {
166
self.inner.shrink_to_fit();
167
return Ok(());
168
}
169
170
let (ptr, len, cap) = mem::take(self).into_raw_parts();
171
let layout = Layout::array::<T>(cap).unwrap();
172
let new_size = Layout::array::<T>(len).unwrap().size();
173
174
// SAFETY: `ptr` was previously allocated in the global allocator,
175
// `layout` has a nonzero size and matches the current allocation of
176
// `ptr`, `new_size` is nonzero, and `new_size` is a valid array size
177
// for `len` elements given its constructor.
178
let result = unsafe { try_realloc(ptr.cast(), layout, new_size) };
179
180
match result {
181
Ok(ptr) => {
182
// SAFETY: `result` is allocated with the global allocator and
183
// has room for exactly `[T; len]`.
184
*self = unsafe { Self::from_raw_parts(ptr.cast::<T>().as_ptr(), len, len) };
185
Ok(())
186
}
187
Err(oom) => {
188
// SAFETY: If reallocation fails then it's guaranteed that the
189
// original allocation is not tampered with, so it's safe to
190
// reassemble the original vector.
191
*self = unsafe { Vec::from_raw_parts(ptr, len, cap) };
192
Err(oom)
193
}
194
}
195
}
196
197
/// Same as [`std::vec::Vec::into_boxed_slice`] but returns an error on
198
/// allocation failure.
199
pub fn into_boxed_slice(mut self) -> Result<Box<[T]>, OutOfMemory> {
200
self.shrink_to_fit()?;
201
202
// Once we've shrunken the allocation to just the actual length, we can
203
// use `std`'s `into_boxed_slice` without fear of `realloc`.
204
Ok(self.inner.into_boxed_slice())
205
}
206
}
207
208
impl<T> Deref for Vec<T> {
209
type Target = [T];
210
211
fn deref(&self) -> &Self::Target {
212
&self.inner
213
}
214
}
215
216
impl<T> DerefMut for Vec<T> {
217
fn deref_mut(&mut self) -> &mut Self::Target {
218
&mut self.inner
219
}
220
}
221
222
impl<T> Index<usize> for Vec<T> {
223
type Output = T;
224
225
fn index(&self, index: usize) -> &Self::Output {
226
&self.inner[index]
227
}
228
}
229
230
impl<T> IndexMut<usize> for Vec<T> {
231
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
232
&mut self.inner[index]
233
}
234
}
235
236
impl<T> IntoIterator for Vec<T> {
237
type Item = T;
238
type IntoIter = std_alloc::vec::IntoIter<T>;
239
240
fn into_iter(self) -> Self::IntoIter {
241
self.inner.into_iter()
242
}
243
}
244
245
impl<'a, T> IntoIterator for &'a Vec<T> {
246
type Item = &'a T;
247
248
type IntoIter = core::slice::Iter<'a, T>;
249
250
fn into_iter(self) -> Self::IntoIter {
251
(**self).iter()
252
}
253
}
254
255
impl<'a, T> IntoIterator for &'a mut Vec<T> {
256
type Item = &'a mut T;
257
258
type IntoIter = core::slice::IterMut<'a, T>;
259
260
fn into_iter(self) -> Self::IntoIter {
261
(**self).iter_mut()
262
}
263
}
264
265
impl<T> From<Box<[T]>> for Vec<T> {
266
fn from(boxed_slice: Box<[T]>) -> Self {
267
Vec {
268
inner: StdVec::from(boxed_slice),
269
}
270
}
271
}
272
273
#[cfg(test)]
274
mod tests {
275
use super::Vec;
276
use crate::error::OutOfMemory;
277
278
#[test]
279
fn test_into_boxed_slice() -> Result<(), OutOfMemory> {
280
assert_eq!(*Vec::<i32>::new().into_boxed_slice()?, []);
281
282
let mut vec = Vec::new();
283
vec.push(1)?;
284
assert_eq!(*vec.into_boxed_slice()?, [1]);
285
286
let mut vec = Vec::with_capacity(2)?;
287
vec.push(1)?;
288
assert_eq!(*vec.into_boxed_slice()?, [1]);
289
290
let mut vec = Vec::with_capacity(2)?;
291
vec.push(1_u128)?;
292
assert_eq!(*vec.into_boxed_slice()?, [1]);
293
294
assert_eq!(*Vec::<()>::new().into_boxed_slice()?, []);
295
296
let mut vec = Vec::new();
297
vec.push(())?;
298
assert_eq!(*vec.into_boxed_slice()?, [()]);
299
300
let vec = Vec::<i32>::with_capacity(2)?;
301
assert_eq!(*vec.into_boxed_slice()?, []);
302
Ok(())
303
}
304
}
305
306