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