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