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