1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use alloc::{Alloc, Layout, Global};
15 use core::ptr::{self, Unique};
17 use super::boxed::Box;
18 use super::allocator::CollectionAllocErr;
19 use super::allocator::CollectionAllocErr::*;
21 /// A low-level utility for more ergonomically allocating, reallocating, and deallocating
22 /// a buffer of memory on the heap without having to worry about all the corner cases
23 /// involved. This type is excellent for building your own data structures like Vec and VecDeque.
26 /// * Produces Unique::empty() on zero-sized types
27 /// * Produces Unique::empty() on zero-length allocations
28 /// * Catches all overflows in capacity computations (promotes them to "capacity overflow" panics)
29 /// * Guards against 32-bit systems allocating more than isize::MAX bytes
30 /// * Guards against overflowing your length
32 /// * Avoids freeing Unique::empty()
33 /// * Contains a ptr::Unique and thus endows the user with all related benefits
35 /// This type does not in anyway inspect the memory that it manages. When dropped it *will*
36 /// free its memory, but it *won't* try to Drop its contents. It is up to the user of RawVec
37 /// to handle the actual things *stored* inside of a RawVec.
39 /// Note that a RawVec always forces its capacity to be usize::MAX for zero-sized types.
40 /// This enables you to use capacity growing logic catch the overflows in your length
41 /// that might occur with zero-sized types.
43 /// However this means that you need to be careful when roundtripping this type
44 /// with a `Box<[T]>`: `cap()` won't yield the len. However `with_capacity`,
45 /// `shrink_to_fit`, and `from_box` will actually set RawVec's private capacity
46 /// field. This allows zero-sized types to not be special-cased by consumers of
48 #[allow(missing_debug_implementations)]
49 pub struct RawVec<T, A: Alloc = Global> {
55 impl<T, A: Alloc> RawVec<T, A> {
56 /// Like `new` but parameterized over the choice of allocator for
57 /// the returned RawVec.
58 pub fn new_in(a: A) -> Self {
59 // !0 is usize::MAX. This branch should be stripped at compile time.
60 let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };
62 // Unique::empty() doubles as "unallocated" and "zero-sized allocation"
70 /// Like `with_capacity` but parameterized over the choice of
71 /// allocator for the returned RawVec.
73 pub fn with_capacity_in(cap: usize, a: A) -> Self {
74 RawVec::allocate_in(cap, false, a)
77 /// Like `with_capacity_zeroed` but parameterized over the choice
78 /// of allocator for the returned RawVec.
80 pub fn with_capacity_zeroed_in(cap: usize, a: A) -> Self {
81 RawVec::allocate_in(cap, true, a)
84 fn allocate_in(cap: usize, zeroed: bool, mut a: A) -> Self {
86 let elem_size = mem::size_of::<T>();
88 let alloc_size = cap.checked_mul(elem_size).expect("capacity overflow");
89 alloc_guard(alloc_size).expect("capacity overflow");
91 // handles ZSTs and `cap = 0` alike
92 let ptr = if alloc_size == 0 {
93 mem::align_of::<T>() as *mut u8
95 let align = mem::align_of::<T>();
96 let result = if zeroed {
97 a.alloc_zeroed(Layout::from_size_align(alloc_size, align).unwrap())
99 a.alloc(Layout::from_size_align(alloc_size, align).unwrap())
108 ptr: Unique::new_unchecked(ptr as *mut _),
116 impl<T> RawVec<T, Global> {
117 /// Creates the biggest possible RawVec (on the system heap)
118 /// without allocating. If T has positive size, then this makes a
119 /// RawVec with capacity 0. If T has 0 size, then it makes a
120 /// RawVec with capacity `usize::MAX`. Useful for implementing
121 /// delayed allocation.
122 pub fn new() -> Self {
126 /// Creates a RawVec (on the system heap) with exactly the
127 /// capacity and alignment requirements for a `[T; cap]`. This is
128 /// equivalent to calling RawVec::new when `cap` is 0 or T is
129 /// zero-sized. Note that if `T` is zero-sized this means you will
130 /// *not* get a RawVec with the requested capacity!
134 /// * Panics if the requested capacity exceeds `usize::MAX` bytes.
135 /// * Panics on 32-bit platforms if the requested capacity exceeds
136 /// `isize::MAX` bytes.
142 pub fn with_capacity(cap: usize) -> Self {
143 RawVec::allocate_in(cap, false, Global)
146 /// Like `with_capacity` but guarantees the buffer is zeroed.
148 pub fn with_capacity_zeroed(cap: usize) -> Self {
149 RawVec::allocate_in(cap, true, Global)
153 impl<T, A: Alloc> RawVec<T, A> {
154 /// Reconstitutes a RawVec from a pointer, capacity, and allocator.
156 /// # Undefined Behavior
158 /// The ptr must be allocated (via the given allocator `a`), and with the given capacity. The
159 /// capacity cannot exceed `isize::MAX` (only a concern on 32-bit systems).
160 /// If the ptr and capacity come from a RawVec created via `a`, then this is guaranteed.
161 pub unsafe fn from_raw_parts_in(ptr: *mut T, cap: usize, a: A) -> Self {
163 ptr: Unique::new_unchecked(ptr),
170 impl<T> RawVec<T, Global> {
171 /// Reconstitutes a RawVec from a pointer, capacity.
173 /// # Undefined Behavior
175 /// The ptr must be allocated (on the system heap), and with the given capacity. The
176 /// capacity cannot exceed `isize::MAX` (only a concern on 32-bit systems).
177 /// If the ptr and capacity come from a RawVec, then this is guaranteed.
178 pub unsafe fn from_raw_parts(ptr: *mut T, cap: usize) -> Self {
180 ptr: Unique::new_unchecked(ptr),
186 /// Converts a `Box<[T]>` into a `RawVec<T>`.
187 pub fn from_box(mut slice: Box<[T]>) -> Self {
189 let result = RawVec::from_raw_parts(slice.as_mut_ptr(), slice.len());
196 impl<T, A: Alloc> RawVec<T, A> {
197 /// Gets a raw pointer to the start of the allocation. Note that this is
198 /// Unique::empty() if `cap = 0` or T is zero-sized. In the former case, you must
200 pub fn ptr(&self) -> *mut T {
204 /// Gets the capacity of the allocation.
206 /// This will always be `usize::MAX` if `T` is zero-sized.
208 pub fn cap(&self) -> usize {
209 if mem::size_of::<T>() == 0 {
216 /// Returns a shared reference to the allocator backing this RawVec.
217 pub fn alloc(&self) -> &A {
221 /// Returns a mutable reference to the allocator backing this RawVec.
222 pub fn alloc_mut(&mut self) -> &mut A {
226 fn current_layout(&self) -> Option<Layout> {
230 // We have an allocated chunk of memory, so we can bypass runtime
231 // checks to get our current layout.
233 let align = mem::align_of::<T>();
234 let size = mem::size_of::<T>() * self.cap;
235 Some(Layout::from_size_align_unchecked(size, align))
240 /// Doubles the size of the type's backing allocation. This is common enough
241 /// to want to do that it's easiest to just have a dedicated method. Slightly
242 /// more efficient logic can be provided for this than the general case.
244 /// This function is ideal for when pushing elements one-at-a-time because
245 /// you don't need to incur the costs of the more general computations
246 /// reserve needs to do to guard against overflow. You do however need to
247 /// manually check if your `len == cap`.
251 /// * Panics if T is zero-sized on the assumption that you managed to exhaust
252 /// all `usize::MAX` slots in your imaginary buffer.
253 /// * Panics on 32-bit platforms if the requested capacity exceeds
254 /// `isize::MAX` bytes.
263 /// # #![feature(alloc)]
264 /// # extern crate alloc;
266 /// # use alloc::raw_vec::RawVec;
267 /// struct MyVec<T> {
272 /// impl<T> MyVec<T> {
273 /// pub fn push(&mut self, elem: T) {
274 /// if self.len == self.buf.cap() { self.buf.double(); }
275 /// // double would have aborted or panicked if the len exceeded
276 /// // `isize::MAX` so this is safe to do unchecked now.
278 /// ptr::write(self.buf.ptr().offset(self.len as isize), elem);
284 /// # let mut vec = MyVec { buf: RawVec::new(), len: 0 };
290 pub fn double(&mut self) {
292 let elem_size = mem::size_of::<T>();
294 // since we set the capacity to usize::MAX when elem_size is
295 // 0, getting to here necessarily means the RawVec is overfull.
296 assert!(elem_size != 0, "capacity overflow");
298 let (new_cap, uniq) = match self.current_layout() {
300 // Since we guarantee that we never allocate more than
301 // isize::MAX bytes, `elem_size * self.cap <= isize::MAX` as
302 // a precondition, so this can't overflow. Additionally the
303 // alignment will never be too large as to "not be
304 // satisfiable", so `Layout::from_size_align` will always
307 // tl;dr; we bypass runtime checks due to dynamic assertions
308 // in this module, allowing us to use
309 // `from_size_align_unchecked`.
310 let new_cap = 2 * self.cap;
311 let new_size = new_cap * elem_size;
312 let new_layout = Layout::from_size_align_unchecked(new_size, cur.align());
313 alloc_guard(new_size).expect("capacity overflow");
314 let ptr_res = self.a.realloc(self.ptr.as_ptr() as *mut u8,
318 Ok(ptr) => (new_cap, Unique::new_unchecked(ptr as *mut T)),
319 Err(_) => self.a.oom(),
323 // skip to 4 because tiny Vec's are dumb; but not if that
324 // would cause overflow
325 let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
326 match self.a.alloc_array::<T>(new_cap) {
327 Ok(ptr) => (new_cap, ptr.into()),
328 Err(_) => self.a.oom(),
337 /// Attempts to double the size of the type's backing allocation in place. This is common
338 /// enough to want to do that it's easiest to just have a dedicated method. Slightly
339 /// more efficient logic can be provided for this than the general case.
341 /// Returns true if the reallocation attempt has succeeded, or false otherwise.
345 /// * Panics if T is zero-sized on the assumption that you managed to exhaust
346 /// all `usize::MAX` slots in your imaginary buffer.
347 /// * Panics on 32-bit platforms if the requested capacity exceeds
348 /// `isize::MAX` bytes.
351 pub fn double_in_place(&mut self) -> bool {
353 let elem_size = mem::size_of::<T>();
354 let old_layout = match self.current_layout() {
355 Some(layout) => layout,
356 None => return false, // nothing to double
359 // since we set the capacity to usize::MAX when elem_size is
360 // 0, getting to here necessarily means the RawVec is overfull.
361 assert!(elem_size != 0, "capacity overflow");
363 // Since we guarantee that we never allocate more than isize::MAX
364 // bytes, `elem_size * self.cap <= isize::MAX` as a precondition, so
365 // this can't overflow.
367 // Similarly like with `double` above we can go straight to
368 // `Layout::from_size_align_unchecked` as we know this won't
369 // overflow and the alignment is sufficiently small.
370 let new_cap = 2 * self.cap;
371 let new_size = new_cap * elem_size;
372 alloc_guard(new_size).expect("capacity overflow");
373 let ptr = self.ptr() as *mut _;
374 let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align());
375 match self.a.grow_in_place(ptr, old_layout, new_layout) {
377 // We can't directly divide `size`.
388 /// Ensures that the buffer contains at least enough space to hold
389 /// `used_cap + needed_extra_cap` elements. If it doesn't already,
390 /// will reallocate the minimum possible amount of memory necessary.
391 /// Generally this will be exactly the amount of memory necessary,
392 /// but in principle the allocator is free to give back more than
395 /// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate
396 /// the requested space. This is not really unsafe, but the unsafe
397 /// code *you* write that relies on the behavior of this function may break.
401 /// * Panics if the requested capacity exceeds `usize::MAX` bytes.
402 /// * Panics on 32-bit platforms if the requested capacity exceeds
403 /// `isize::MAX` bytes.
408 pub fn try_reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize)
409 -> Result<(), CollectionAllocErr> {
412 // NOTE: we don't early branch on ZSTs here because we want this
413 // to actually catch "asking for more than usize::MAX" in that case.
414 // If we make it past the first branch then we are guaranteed to
417 // Don't actually need any more capacity.
418 // Wrapping in case they gave a bad `used_cap`.
419 if self.cap().wrapping_sub(used_cap) >= needed_extra_cap {
423 // Nothing we can really do about these checks :(
424 let new_cap = used_cap.checked_add(needed_extra_cap).ok_or(CapacityOverflow)?;
425 let new_layout = Layout::array::<T>(new_cap).ok_or(CapacityOverflow)?;
427 alloc_guard(new_layout.size())?;
429 let res = match self.current_layout() {
431 let old_ptr = self.ptr.as_ptr() as *mut u8;
432 self.a.realloc(old_ptr, layout, new_layout)
434 None => self.a.alloc(new_layout),
437 self.ptr = Unique::new_unchecked(res? as *mut T);
444 pub fn reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize) {
445 match self.try_reserve_exact(used_cap, needed_extra_cap) {
446 Err(CapacityOverflow) => panic!("capacity overflow"),
447 Err(AllocErr(_)) => self.a.oom(),
448 Ok(()) => { /* yay */ }
452 /// Calculates the buffer's new size given that it'll hold `used_cap +
453 /// needed_extra_cap` elements. This logic is used in amortized reserve methods.
454 /// Returns `(new_capacity, new_alloc_size)`.
455 fn amortized_new_size(&self, used_cap: usize, needed_extra_cap: usize)
456 -> Result<usize, CollectionAllocErr> {
458 // Nothing we can really do about these checks :(
459 let required_cap = used_cap.checked_add(needed_extra_cap).ok_or(CapacityOverflow)?;
460 // Cannot overflow, because `cap <= isize::MAX`, and type of `cap` is `usize`.
461 let double_cap = self.cap * 2;
462 // `double_cap` guarantees exponential growth.
463 Ok(cmp::max(double_cap, required_cap))
466 /// Ensures that the buffer contains at least enough space to hold
467 /// `used_cap + needed_extra_cap` elements. If it doesn't already have
468 /// enough capacity, will reallocate enough space plus comfortable slack
469 /// space to get amortized `O(1)` behavior. Will limit this behavior
470 /// if it would needlessly cause itself to panic.
472 /// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate
473 /// the requested space. This is not really unsafe, but the unsafe
474 /// code *you* write that relies on the behavior of this function may break.
476 /// This is ideal for implementing a bulk-push operation like `extend`.
480 /// * Panics if the requested capacity exceeds `usize::MAX` bytes.
481 /// * Panics on 32-bit platforms if the requested capacity exceeds
482 /// `isize::MAX` bytes.
491 /// # #![feature(alloc)]
492 /// # extern crate alloc;
494 /// # use alloc::raw_vec::RawVec;
495 /// struct MyVec<T> {
500 /// impl<T: Clone> MyVec<T> {
501 /// pub fn push_all(&mut self, elems: &[T]) {
502 /// self.buf.reserve(self.len, elems.len());
503 /// // reserve would have aborted or panicked if the len exceeded
504 /// // `isize::MAX` so this is safe to do unchecked now.
507 /// ptr::write(self.buf.ptr().offset(self.len as isize), x.clone());
514 /// # let mut vector = MyVec { buf: RawVec::new(), len: 0 };
515 /// # vector.push_all(&[1, 3, 5, 7, 9]);
518 pub fn try_reserve(&mut self, used_cap: usize, needed_extra_cap: usize)
519 -> Result<(), CollectionAllocErr> {
521 // NOTE: we don't early branch on ZSTs here because we want this
522 // to actually catch "asking for more than usize::MAX" in that case.
523 // If we make it past the first branch then we are guaranteed to
526 // Don't actually need any more capacity.
527 // Wrapping in case they give a bad `used_cap`
528 if self.cap().wrapping_sub(used_cap) >= needed_extra_cap {
532 let new_cap = self.amortized_new_size(used_cap, needed_extra_cap)?;
533 let new_layout = Layout::array::<T>(new_cap).ok_or(CapacityOverflow)?;
535 // FIXME: may crash and burn on over-reserve
536 alloc_guard(new_layout.size())?;
538 let res = match self.current_layout() {
540 let old_ptr = self.ptr.as_ptr() as *mut u8;
541 self.a.realloc(old_ptr, layout, new_layout)
543 None => self.a.alloc(new_layout),
546 self.ptr = Unique::new_unchecked(res? as *mut T);
553 /// The same as try_reserve, but errors are lowered to a call to oom().
554 pub fn reserve(&mut self, used_cap: usize, needed_extra_cap: usize) {
555 match self.try_reserve(used_cap, needed_extra_cap) {
556 Err(CapacityOverflow) => panic!("capacity overflow"),
557 Err(AllocErr(_)) => self.a.oom(),
558 Ok(()) => { /* yay */ }
561 /// Attempts to ensure that the buffer contains at least enough space to hold
562 /// `used_cap + needed_extra_cap` elements. If it doesn't already have
563 /// enough capacity, will reallocate in place enough space plus comfortable slack
564 /// space to get amortized `O(1)` behavior. Will limit this behaviour
565 /// if it would needlessly cause itself to panic.
567 /// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate
568 /// the requested space. This is not really unsafe, but the unsafe
569 /// code *you* write that relies on the behavior of this function may break.
571 /// Returns true if the reallocation attempt has succeeded, or false otherwise.
575 /// * Panics if the requested capacity exceeds `usize::MAX` bytes.
576 /// * Panics on 32-bit platforms if the requested capacity exceeds
577 /// `isize::MAX` bytes.
578 pub fn reserve_in_place(&mut self, used_cap: usize, needed_extra_cap: usize) -> bool {
580 // NOTE: we don't early branch on ZSTs here because we want this
581 // to actually catch "asking for more than usize::MAX" in that case.
582 // If we make it past the first branch then we are guaranteed to
585 // Don't actually need any more capacity. If the current `cap` is 0, we can't
586 // reallocate in place.
587 // Wrapping in case they give a bad `used_cap`
588 let old_layout = match self.current_layout() {
589 Some(layout) => layout,
590 None => return false,
592 if self.cap().wrapping_sub(used_cap) >= needed_extra_cap {
596 let new_cap = self.amortized_new_size(used_cap, needed_extra_cap)
597 .expect("capacity overflow");
599 // Here, `cap < used_cap + needed_extra_cap <= new_cap`
600 // (regardless of whether `self.cap - used_cap` wrapped).
601 // Therefore we can safely call grow_in_place.
603 let ptr = self.ptr() as *mut _;
604 let new_layout = Layout::new::<T>().repeat(new_cap).unwrap().0;
605 // FIXME: may crash and burn on over-reserve
606 alloc_guard(new_layout.size()).expect("capacity overflow");
607 match self.a.grow_in_place(ptr, old_layout, new_layout) {
619 /// Shrinks the allocation down to the specified amount. If the given amount
620 /// is 0, actually completely deallocates.
624 /// Panics if the given amount is *larger* than the current capacity.
629 pub fn shrink_to_fit(&mut self, amount: usize) {
630 let elem_size = mem::size_of::<T>();
632 // Set the `cap` because they might be about to promote to a `Box<[T]>`
638 // This check is my waterloo; it's the only thing Vec wouldn't have to do.
639 assert!(self.cap >= amount, "Tried to shrink to a larger capacity");
642 // We want to create a new zero-length vector within the
643 // same allocator. We use ptr::write to avoid an
644 // erroneous attempt to drop the contents, and we use
645 // ptr::read to sidestep condition against destructuring
646 // types that implement Drop.
649 let a = ptr::read(&self.a as *const A);
650 self.dealloc_buffer();
651 ptr::write(self, RawVec::new_in(a));
653 } else if self.cap != amount {
655 // We know here that our `amount` is greater than zero. This
656 // implies, via the assert above, that capacity is also greater
657 // than zero, which means that we've got a current layout that
660 // We also know that `self.cap` is greater than `amount`, and
661 // consequently we don't need runtime checks for creating either
663 let old_size = elem_size * self.cap;
664 let new_size = elem_size * amount;
665 let align = mem::align_of::<T>();
666 let old_layout = Layout::from_size_align_unchecked(old_size, align);
667 let new_layout = Layout::from_size_align_unchecked(new_size, align);
668 match self.a.realloc(self.ptr.as_ptr() as *mut u8,
671 Ok(p) => self.ptr = Unique::new_unchecked(p as *mut T),
672 Err(_) => self.a.oom(),
680 impl<T> RawVec<T, Global> {
681 /// Converts the entire buffer into `Box<[T]>`.
683 /// While it is not *strictly* Undefined Behavior to call
684 /// this procedure while some of the RawVec is uninitialized,
685 /// it certainly makes it trivial to trigger it.
687 /// Note that this will correctly reconstitute any `cap` changes
688 /// that may have been performed. (see description of type for details)
689 pub unsafe fn into_box(self) -> Box<[T]> {
690 // NOTE: not calling `cap()` here, actually using the real `cap` field!
691 let slice = slice::from_raw_parts_mut(self.ptr(), self.cap);
692 let output: Box<[T]> = Box::from_raw(slice);
698 impl<T, A: Alloc> RawVec<T, A> {
699 /// Frees the memory owned by the RawVec *without* trying to Drop its contents.
700 pub unsafe fn dealloc_buffer(&mut self) {
701 let elem_size = mem::size_of::<T>();
703 if let Some(layout) = self.current_layout() {
704 let ptr = self.ptr() as *mut u8;
705 self.a.dealloc(ptr, layout);
711 unsafe impl<#[may_dangle] T, A: Alloc> Drop for RawVec<T, A> {
712 /// Frees the memory owned by the RawVec *without* trying to Drop its contents.
714 unsafe { self.dealloc_buffer(); }
720 // We need to guarantee the following:
721 // * We don't ever allocate `> isize::MAX` byte-size objects
722 // * We don't overflow `usize::MAX` and actually allocate too little
724 // On 64-bit we just need to check for overflow since trying to allocate
725 // `> isize::MAX` bytes will surely fail. On 32-bit and 16-bit we need to add
726 // an extra guard for this in case we're running on a platform which can use
727 // all 4GB in user-space. e.g. PAE or x32
730 fn alloc_guard(alloc_size: usize) -> Result<(), CollectionAllocErr> {
731 if mem::size_of::<usize>() < 8 && alloc_size > ::core::isize::MAX as usize {
732 Err(CapacityOverflow)
743 fn allocator_param() {
744 use allocator::{Alloc, AllocErr};
746 // Writing a test of integration between third-party
747 // allocators and RawVec is a little tricky because the RawVec
748 // API does not expose fallible allocation methods, so we
749 // cannot check what happens when allocator is exhausted
750 // (beyond detecting a panic).
752 // Instead, this just checks that the RawVec methods do at
753 // least go through the Allocator API when it reserves
756 // A dumb allocator that consumes a fixed amount of fuel
757 // before allocation attempts start failing.
758 struct BoundedAlloc { fuel: usize }
759 unsafe impl Alloc for BoundedAlloc {
760 unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
761 let size = layout.size();
762 if size > self.fuel {
763 return Err(AllocErr);
765 match Global.alloc(layout) {
766 ok @ Ok(_) => { self.fuel -= size; ok }
770 unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
771 Global.dealloc(ptr, layout)
775 let a = BoundedAlloc { fuel: 500 };
776 let mut v: RawVec<u8, _> = RawVec::with_capacity_in(50, a);
777 assert_eq!(v.a.fuel, 450);
778 v.reserve(50, 150); // (causes a realloc, thus using 50 + 150 = 200 units of fuel)
779 assert_eq!(v.a.fuel, 250);
783 fn reserve_does_not_overallocate() {
785 let mut v: RawVec<u32> = RawVec::new();
786 // First `reserve` allocates like `reserve_exact`
788 assert_eq!(9, v.cap());
792 let mut v: RawVec<u32> = RawVec::new();
794 assert_eq!(7, v.cap());
795 // 97 if more than double of 7, so `reserve` should work
796 // like `reserve_exact`.
798 assert_eq!(97, v.cap());
802 let mut v: RawVec<u32> = RawVec::new();
804 assert_eq!(12, v.cap());
806 // 3 is less than half of 12, so `reserve` must grow
807 // exponentially. At the time of writing this test grow
808 // factor is 2, so new capacity is 24, however, grow factor
809 // of 1.5 is OK too. Hence `>= 18` in assert.
810 assert!(v.cap() >= 12 + 12 / 2);