xref: /wasmtime-44.0.1/crates/core/src/alloc/vec.rs (revision 7e11f182)
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