xref: /wasmtime-44.0.1/crates/core/src/alloc/vec.rs (revision 439de7fb)
1 use crate::alloc::{TryClone, try_realloc};
2 use crate::error::OutOfMemory;
3 use core::borrow::Borrow;
4 use core::{
5     cmp::Ordering,
6     fmt, mem,
7     num::NonZeroUsize,
8     ops::{Deref, DerefMut, Index, IndexMut},
9     slice::SliceIndex,
10 };
11 #[cfg(feature = "serde")]
12 use serde::ser::SerializeSeq;
13 use std_alloc::alloc::Layout;
14 use std_alloc::boxed::Box;
15 use std_alloc::vec::Vec as StdVec;
16 
17 /// Same as the [`std::vec!`] macro but returns an error on allocation failure.
18 #[macro_export]
19 macro_rules! try_vec {
20     ( $( $elem:expr ),* ) => {{
21         let len = $crate::private_len!( $( $elem ),* );
22         $crate::alloc::TryVec::with_capacity(len).and_then(|mut v| {
23             $( v.push($elem)?; )*
24             let _ = &mut v;
25             Ok(v)
26         })
27     }};
28 
29     ( $elem:expr; $len:expr ) => {{
30         let len: usize = $len;
31         if let Some(len) = ::core::num::NonZeroUsize::new(len) {
32             let elem = $elem;
33             $crate::alloc::TryVec::from_elem(elem, len)
34         } else {
35             Ok($crate::alloc::TryVec::new())
36         }
37     }};
38 
39 }
40 
41 // Only for use by the `vec!` macro.
42 #[doc(hidden)]
43 #[macro_export]
44 macro_rules! private_len {
45     ( ) => { 0 };
46     ( $e:expr $( , $es:expr )* ) => { 1 + $crate::private_len!( $( $es ),* ) };
47 }
48 
49 /// Like `std::vec::Vec` but all methods that allocate force handling allocation
50 /// failure.
51 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
52 pub struct TryVec<T> {
53     inner: StdVec<T>,
54 }
55 
56 impl<T> Default for TryVec<T> {
default() -> Self57     fn default() -> Self {
58         Self {
59             inner: Default::default(),
60         }
61     }
62 }
63 
64 impl<T: fmt::Debug> fmt::Debug for TryVec<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result65     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66         fmt::Debug::fmt(&self.inner, f)
67     }
68 }
69 
70 impl<T> TryClone for TryVec<T>
71 where
72     T: TryClone,
73 {
try_clone(&self) -> Result<Self, OutOfMemory>74     fn try_clone(&self) -> Result<Self, OutOfMemory> {
75         let mut v = TryVec::with_capacity(self.len())?;
76         for x in self {
77             v.push(x.try_clone()?).expect("reserved capacity");
78         }
79         Ok(v)
80     }
81 }
82 
83 impl<T> TryVec<T> {
84     /// Same as [`std::vec::Vec::new`].
new() -> Self85     pub const fn new() -> Self {
86         Self {
87             inner: StdVec::new(),
88         }
89     }
90 
91     /// Same as [`std::vec::Vec::with_capacity`] but returns an error on
92     /// allocation failure.
with_capacity(capacity: usize) -> Result<Self, OutOfMemory>93     pub fn with_capacity(capacity: usize) -> Result<Self, OutOfMemory> {
94         let mut v = Self::new();
95         v.reserve(capacity)?;
96         Ok(v)
97     }
98 
99     // For use with the `vec!` macro.
100     #[doc(hidden)]
101     #[inline]
from_elem(elem: T, len: NonZeroUsize) -> Result<Self, OutOfMemory> where T: TryClone,102     pub fn from_elem(elem: T, len: NonZeroUsize) -> Result<Self, OutOfMemory>
103     where
104         T: TryClone,
105     {
106         let mut v = Self::with_capacity(len.get())?;
107 
108         // Minimize calls to `TryClone` by always pushing `elem` itself as the
109         // last element.
110         for _ in 0..len.get() - 1 {
111             v.push(elem.try_clone()?)?;
112         }
113         v.push(elem)?;
114 
115         Ok(v)
116     }
117 
118     /// Same as [`std::vec::Vec::reserve`] but returns an error on allocation
119     /// failure.
reserve(&mut self, additional: usize) -> Result<(), OutOfMemory>120     pub fn reserve(&mut self, additional: usize) -> Result<(), OutOfMemory> {
121         self.inner.try_reserve(additional).map_err(|_| {
122             OutOfMemory::new(
123                 self.len()
124                     .saturating_add(additional)
125                     .saturating_mul(mem::size_of::<T>()),
126             )
127         })
128     }
129 
130     /// Same as [`std::vec::Vec::reserve_exact`] but returns an error on allocation
131     /// failure.
reserve_exact(&mut self, additional: usize) -> Result<(), OutOfMemory>132     pub fn reserve_exact(&mut self, additional: usize) -> Result<(), OutOfMemory> {
133         self.inner
134             .try_reserve_exact(additional)
135             .map_err(|_| OutOfMemory::new(self.len().saturating_add(additional)))
136     }
137 
138     /// Same as [`std::vec::Vec::len`].
len(&self) -> usize139     pub fn len(&self) -> usize {
140         self.inner.len()
141     }
142 
143     /// Same as [`std::vec::Vec::capacity`].
capacity(&self) -> usize144     pub fn capacity(&self) -> usize {
145         self.inner.capacity()
146     }
147 
148     /// Same as [`std::vec::Vec::is_empty`].
is_empty(&self) -> bool149     pub fn is_empty(&self) -> bool {
150         self.inner.is_empty()
151     }
152 
153     /// Same as [`std::vec::Vec::push`] but returns an error on allocation
154     /// failure.
push(&mut self, value: T) -> Result<(), OutOfMemory>155     pub fn push(&mut self, value: T) -> Result<(), OutOfMemory> {
156         self.reserve(1)?;
157         self.inner.push(value);
158         Ok(())
159     }
160 
161     /// Same as [`std::vec::Vec::pop`].
pop(&mut self) -> Option<T>162     pub fn pop(&mut self) -> Option<T> {
163         self.inner.pop()
164     }
165 
166     /// Same as [`std::vec::Vec::truncate`].
truncate(&mut self, len: usize)167     pub fn truncate(&mut self, len: usize) {
168         self.inner.truncate(len);
169     }
170 
171     /// Same as [`std::vec::Vec::resize`] but returns an error on allocation
172     /// failure.
resize(&mut self, new_len: usize, value: T) -> Result<(), OutOfMemory> where T: TryClone,173     pub fn resize(&mut self, new_len: usize, value: T) -> Result<(), OutOfMemory>
174     where
175         T: TryClone,
176     {
177         match new_len.cmp(&self.len()) {
178             Ordering::Less => self.truncate(new_len),
179             Ordering::Equal => {}
180             Ordering::Greater => {
181                 let delta = new_len - self.len();
182                 self.reserve(delta)?;
183                 // Minimize `try_clone` calls by always pushing `value` directly
184                 // as the last element.
185                 for _ in 0..delta - 1 {
186                     self.push(value.try_clone()?)?;
187                 }
188                 self.push(value)?;
189             }
190         }
191         Ok(())
192     }
193 
194     /// Same as [`std::vec::Vec::resize_with`] but returns an error on
195     /// allocation failure.
resize_with<F>(&mut self, new_len: usize, f: F) -> Result<(), OutOfMemory> where F: FnMut() -> T,196     pub fn resize_with<F>(&mut self, new_len: usize, f: F) -> Result<(), OutOfMemory>
197     where
198         F: FnMut() -> T,
199     {
200         let len = self.len();
201         if new_len > len {
202             self.reserve(new_len - len)?;
203         }
204         self.inner.resize_with(new_len, f);
205         Ok(())
206     }
207 
208     /// Same as [`std::vec::Vec::retain`].
retain<F>(&mut self, f: F) where F: FnMut(&T) -> bool,209     pub fn retain<F>(&mut self, f: F)
210     where
211         F: FnMut(&T) -> bool,
212     {
213         self.inner.retain(f);
214     }
215 
216     /// Same as [`std::vec::Vec::retain_mut`].
retain_mut<F>(&mut self, f: F) where F: FnMut(&mut T) -> bool,217     pub fn retain_mut<F>(&mut self, f: F)
218     where
219         F: FnMut(&mut T) -> bool,
220     {
221         self.inner.retain_mut(f);
222     }
223 
224     /// Same as [`std::vec::Vec::into_raw_parts`].
into_raw_parts(mut self) -> (*mut T, usize, usize)225     pub fn into_raw_parts(mut self) -> (*mut T, usize, usize) {
226         // NB: Can't use `Vec::into_raw_parts` until our MSRV is >= 1.93.
227         #[cfg(not(miri))]
228         {
229             let ptr = self.as_mut_ptr();
230             let len = self.len();
231             let cap = self.capacity();
232             mem::forget(self);
233             (ptr, len, cap)
234         }
235         // NB: Miri requires using `into_raw_parts`, but always run on nightly,
236         // so it's fine to use there.
237         #[cfg(miri)]
238         {
239             let _ = &mut self;
240             self.inner.into_raw_parts()
241         }
242     }
243 
244     /// Same as [`std::vec::Vec::from_raw_parts`].
from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self245     pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self {
246         TryVec {
247             // Safety: Same as our unsafe contract.
248             inner: unsafe { StdVec::from_raw_parts(ptr, length, capacity) },
249         }
250     }
251 
252     /// Same as [`std::vec::Vec::drain`].
drain<R>(&mut self, range: R) -> std_alloc::vec::Drain<'_, T> where R: core::ops::RangeBounds<usize>,253     pub fn drain<R>(&mut self, range: R) -> std_alloc::vec::Drain<'_, T>
254     where
255         R: core::ops::RangeBounds<usize>,
256     {
257         self.inner.drain(range)
258     }
259 
260     /// Same as [`std::vec::Vec::shrink_to_fit`] but returns an error on
261     /// allocation failure.
shrink_to_fit(&mut self) -> Result<(), OutOfMemory>262     pub fn shrink_to_fit(&mut self) -> Result<(), OutOfMemory> {
263         // If our length is already equal to our capacity, then there is nothing
264         // to shrink.
265         if self.len() == self.capacity() {
266             return Ok(());
267         }
268 
269         // `realloc` requires a non-zero original layout as well as a non-zero
270         // destination layout, so this guard ensures that the sizes below are
271         // all nonzero. This handles a few cases:
272         //
273         // * If `len == cap == 0` then no allocation has ever been made.
274         // * If `len == 0` and `cap != 0` then this function effectively frees
275         //   the memory.
276         // * If `T` is a zero-sized type then nothing's been allocated either.
277         //
278         // In all of these cases delegate to the standard library's
279         // `shrink_to_fit` which is guaranteed to not perform a `realloc`.
280         if self.is_empty() || mem::size_of::<T>() == 0 {
281             self.inner.shrink_to_fit();
282             return Ok(());
283         }
284 
285         let (ptr, len, cap) = mem::take(self).into_raw_parts();
286         let layout = Layout::array::<T>(cap).unwrap();
287         let new_size = Layout::array::<T>(len).unwrap().size();
288 
289         // SAFETY: `ptr` was previously allocated in the global allocator,
290         // `layout` has a nonzero size and matches the current allocation of
291         // `ptr`, `new_size` is nonzero, and `new_size` is a valid array size
292         // for `len` elements given its constructor.
293         let result = unsafe { try_realloc(ptr.cast(), layout, new_size) };
294 
295         match result {
296             Ok(ptr) => {
297                 // SAFETY: `result` is allocated with the global allocator and
298                 // has room for exactly `[T; len]`.
299                 *self = unsafe { Self::from_raw_parts(ptr.cast::<T>().as_ptr(), len, len) };
300                 Ok(())
301             }
302             Err(oom) => {
303                 // SAFETY: If reallocation fails then it's guaranteed that the
304                 // original allocation is not tampered with, so it's safe to
305                 // reassemble the original vector.
306                 *self = unsafe { TryVec::from_raw_parts(ptr, len, cap) };
307                 Err(oom)
308             }
309         }
310     }
311 
312     /// Same as [`std::vec::Vec::into_boxed_slice`] but returns an error on
313     /// allocation failure.
into_boxed_slice(mut self) -> Result<Box<[T]>, OutOfMemory>314     pub fn into_boxed_slice(mut self) -> Result<Box<[T]>, OutOfMemory> {
315         self.shrink_to_fit()?;
316 
317         // Once we've shrunken the allocation to just the actual length, we can
318         // use `std`'s `into_boxed_slice` without fear of `realloc`.
319         Ok(self.inner.into_boxed_slice())
320     }
321 
322     /// Same as [`std::vec::Vec::clear`].
clear(&mut self)323     pub fn clear(&mut self) {
324         self.inner.clear();
325     }
326 
327     /// Same as [`std::vec::Vec::as_mut_ptr`].
328     //
329     // Note that this is technically inherited through the `DerefMut` impl but
330     // that converts `&mut Self` to `&mut [T]` which invalidates all previously
331     // derived pointers. This causes problems in Miri so by having an inherent
332     // method here it means that the borrow scope matches what we want with
333     // Miri.
as_mut_ptr(&mut self) -> *mut T334     pub fn as_mut_ptr(&mut self) -> *mut T {
335         self.inner.as_mut_ptr()
336     }
337 }
338 
339 impl<T> Deref for TryVec<T> {
340     type Target = [T];
341 
deref(&self) -> &Self::Target342     fn deref(&self) -> &Self::Target {
343         &self.inner
344     }
345 }
346 
347 impl<T> DerefMut for TryVec<T> {
deref_mut(&mut self) -> &mut Self::Target348     fn deref_mut(&mut self) -> &mut Self::Target {
349         &mut self.inner
350     }
351 }
352 
353 impl<T> AsRef<[T]> for TryVec<T> {
as_ref(&self) -> &[T]354     fn as_ref(&self) -> &[T] {
355         self
356     }
357 }
358 
359 impl<T> Borrow<[T]> for TryVec<T> {
borrow(&self) -> &[T]360     fn borrow(&self) -> &[T] {
361         self
362     }
363 }
364 
365 impl<T, I> Index<I> for TryVec<T>
366 where
367     I: SliceIndex<[T]>,
368 {
369     type Output = <I as SliceIndex<[T]>>::Output;
370 
index(&self, index: I) -> &Self::Output371     fn index(&self, index: I) -> &Self::Output {
372         &self.inner[index]
373     }
374 }
375 
376 impl<T, I> IndexMut<I> for TryVec<T>
377 where
378     I: SliceIndex<[T]>,
379 {
index_mut(&mut self, index: I) -> &mut Self::Output380     fn index_mut(&mut self, index: I) -> &mut Self::Output {
381         &mut self.inner[index]
382     }
383 }
384 
385 impl<T> IntoIterator for TryVec<T> {
386     type Item = T;
387     type IntoIter = std_alloc::vec::IntoIter<T>;
388 
into_iter(self) -> Self::IntoIter389     fn into_iter(self) -> Self::IntoIter {
390         self.inner.into_iter()
391     }
392 }
393 
394 impl<'a, T> IntoIterator for &'a TryVec<T> {
395     type Item = &'a T;
396 
397     type IntoIter = core::slice::Iter<'a, T>;
398 
into_iter(self) -> Self::IntoIter399     fn into_iter(self) -> Self::IntoIter {
400         (**self).iter()
401     }
402 }
403 
404 impl<'a, T> IntoIterator for &'a mut TryVec<T> {
405     type Item = &'a mut T;
406 
407     type IntoIter = core::slice::IterMut<'a, T>;
408 
into_iter(self) -> Self::IntoIter409     fn into_iter(self) -> Self::IntoIter {
410         (**self).iter_mut()
411     }
412 }
413 
414 impl<T> From<TryVec<T>> for StdVec<T> {
from(v: TryVec<T>) -> Self415     fn from(v: TryVec<T>) -> Self {
416         v.inner
417     }
418 }
419 
420 impl<T> From<StdVec<T>> for TryVec<T> {
from(inner: StdVec<T>) -> Self421     fn from(inner: StdVec<T>) -> Self {
422         Self { inner }
423     }
424 }
425 
426 impl<T> From<Box<[T]>> for TryVec<T> {
from(boxed_slice: Box<[T]>) -> Self427     fn from(boxed_slice: Box<[T]>) -> Self {
428         Self::from(StdVec::from(boxed_slice))
429     }
430 }
431 
432 #[cfg(feature = "serde")]
433 impl<T> serde::ser::Serialize for TryVec<T>
434 where
435     T: serde::ser::Serialize,
436 {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer,437     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
438     where
439         S: serde::Serializer,
440     {
441         let mut seq = serializer.serialize_seq(Some(self.len()))?;
442         for elem in self {
443             seq.serialize_element(elem)?;
444         }
445         seq.end()
446     }
447 }
448 
449 #[cfg(feature = "serde")]
450 impl<'de, T> serde::de::Deserialize<'de> for TryVec<T>
451 where
452     T: serde::de::Deserialize<'de>,
453 {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de>,454     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
455     where
456         D: serde::Deserializer<'de>,
457     {
458         use core::marker::PhantomData;
459 
460         struct Visitor<T>(PhantomData<fn() -> TryVec<T>>);
461 
462         impl<'de, T> serde::de::Visitor<'de> for Visitor<T>
463         where
464             T: serde::de::Deserialize<'de>,
465         {
466             type Value = TryVec<T>;
467 
468             fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
469                 f.write_str("a `wasmtime_core::alloc::Vec` sequence")
470             }
471 
472             fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
473             where
474                 A: serde::de::SeqAccess<'de>,
475             {
476                 use serde::de::Error as _;
477 
478                 let mut v = TryVec::new();
479 
480                 if let Some(len) = seq.size_hint() {
481                     v.reserve_exact(len).map_err(|oom| A::Error::custom(oom))?;
482                 }
483 
484                 while let Some(elem) = seq.next_element()? {
485                     v.push(elem).map_err(|oom| A::Error::custom(oom))?;
486                 }
487 
488                 Ok(v)
489             }
490         }
491 
492         deserializer.deserialize_seq(Visitor(PhantomData))
493     }
494 }
495 
496 #[cfg(test)]
497 mod tests {
498     use super::TryVec;
499     use crate::error::OutOfMemory;
500 
501     #[test]
test_into_boxed_slice() -> Result<(), OutOfMemory>502     fn test_into_boxed_slice() -> Result<(), OutOfMemory> {
503         assert_eq!(*TryVec::<i32>::new().into_boxed_slice()?, []);
504 
505         let mut vec = TryVec::new();
506         vec.push(1)?;
507         assert_eq!(*vec.into_boxed_slice()?, [1]);
508 
509         let mut vec = TryVec::with_capacity(2)?;
510         vec.push(1)?;
511         assert_eq!(*vec.into_boxed_slice()?, [1]);
512 
513         let mut vec = TryVec::with_capacity(2)?;
514         vec.push(1_u128)?;
515         assert_eq!(*vec.into_boxed_slice()?, [1]);
516 
517         assert_eq!(*TryVec::<()>::new().into_boxed_slice()?, []);
518 
519         let mut vec = TryVec::new();
520         vec.push(())?;
521         assert_eq!(*vec.into_boxed_slice()?, [()]);
522 
523         let vec = TryVec::<i32>::with_capacity(2)?;
524         assert_eq!(*vec.into_boxed_slice()?, []);
525         Ok(())
526     }
527 }
528