thin_vec/lib.rs
1#![deny(missing_docs)]
2
3//! `ThinVec` is exactly the same as `Vec`, except that it stores its `len` and `capacity` in the buffer
4//! it allocates.
5//!
6//! This makes the memory footprint of ThinVecs lower; notably in cases where space is reserved for
7//! a non-existence `ThinVec<T>`. So `Vec<ThinVec<T>>` and `Option<ThinVec<T>>::None` will waste less
8//! space. Being pointer-sized also means it can be passed/stored in registers.
9//!
10//! Of course, any actually constructed `ThinVec` will theoretically have a bigger allocation, but
11//! the fuzzy nature of allocators means that might not actually be the case.
12//!
13//! Properties of `Vec` that are preserved:
14//! * `ThinVec::new()` doesn't allocate (it points to a statically allocated singleton)
15//! * reallocation can be done in place
16//! * `size_of::<ThinVec<T>>()` == `size_of::<Option<ThinVec<T>>>()`
17//!
18//! Properties of `Vec` that aren't preserved:
19//! * `ThinVec<T>` can't ever be zero-cost roundtripped to a `Box<[T]>`, `String`, or `*mut T`
20//! * `from_raw_parts` doesn't exist
21//! * `ThinVec` currently doesn't bother to not-allocate for Zero Sized Types (e.g. `ThinVec<()>`),
22//! but it could be done if someone cared enough to implement it.
23//!
24//!
25//! # Optional Features
26//!
27//! # Gecko FFI
28//!
29//! If you enable the gecko-ffi feature, `ThinVec` will verbatim bridge with the nsTArray type in
30//! Gecko (Firefox). That is, `ThinVec` and nsTArray have identical layouts *but not ABIs*,
31//! so nsTArrays/ThinVecs an be natively manipulated by C++ and Rust, and ownership can be
32//! transferred across the FFI boundary (**IF YOU ARE CAREFUL, SEE BELOW!!**).
33//!
34//! While this feature is handy, it is also inherently dangerous to use because Rust and C++ do not
35//! know about each other. Specifically, this can be an issue with non-POD types (types which
36//! have destructors, move constructors, or are `!Copy`).
37//!
38//! ## Do Not Pass By Value
39//!
40//! The biggest thing to keep in mind is that **FFI functions cannot pass ThinVec/nsTArray
41//! by-value**. That is, these are busted APIs:
42//!
43//! ```rust,ignore
44//! // BAD WRONG
45//! extern fn process_data(data: ThinVec<u32>) { ... }
46//! // BAD WRONG
47//! extern fn get_data() -> ThinVec<u32> { ... }
48//! ```
49//!
50//! You must instead pass by-reference:
51//!
52//! ```rust
53//! # use thin_vec::*;
54//! # use std::mem;
55//!
56//! // Read-only access, ok!
57//! extern fn process_data(data: &ThinVec<u32>) {
58//! for val in data {
59//! println!("{}", val);
60//! }
61//! }
62//!
63//! // Replace with empty instance to take ownership, ok!
64//! extern fn consume_data(data: &mut ThinVec<u32>) {
65//! let owned = mem::replace(data, ThinVec::new());
66//! mem::drop(owned);
67//! }
68//!
69//! // Mutate input, ok!
70//! extern fn add_data(dataset: &mut ThinVec<u32>) {
71//! dataset.push(37);
72//! dataset.push(12);
73//! }
74//!
75//! // Return via out-param, usually ok!
76//! //
77//! // WARNING: output must be initialized! (Empty nsTArrays are free, so just do it!)
78//! extern fn get_data(output: &mut ThinVec<u32>) {
79//! *output = thin_vec![1, 2, 3, 4, 5];
80//! }
81//! ```
82//!
83//! Ignorable Explanation For Those Who Really Want To Know Why:
84//!
85//! > The fundamental issue is that Rust and C++ can't currently communicate about destructors, and
86//! > the semantics of C++ require destructors of function arguments to be run when the function
87//! > returns. Whether the callee or caller is responsible for this is also platform-specific, so
88//! > trying to hack around it manually would be messy.
89//! >
90//! > Also a type having a destructor changes its C++ ABI, because that type must actually exist
91//! > in memory (unlike a trivial struct, which is often passed in registers). We don't currently
92//! > have a way to communicate to Rust that this is happening, so even if we worked out the
93//! > destructor issue with say, MaybeUninit, it would still be a non-starter without some RFCs
94//! > to add explicit rustc support.
95//! >
96//! > Realistically, the best answer here is to have a "heavier" bindgen that can secretly
97//! > generate FFI glue so we can pass things "by value" and have it generate by-reference code
98//! > behind our back (like the cxx crate does). This would muddy up debugging/searchfox though.
99//!
100//! ## Types Should Be Trivially Relocatable
101//!
102//! Types in Rust are always trivially relocatable (unless suitably borrowed/[pinned][]/hidden).
103//! This means all Rust types are legal to relocate with a bitwise copy, you cannot provide
104//! copy or move constructors to execute when this happens, and the old location won't have its
105//! destructor run. This will cause problems for types which have a significant location
106//! (types that intrusively point into themselves or have their location registered with a service).
107//!
108//! While relocations are generally predictable if you're very careful, **you should avoid using
109//! types with significant locations with Rust FFI**.
110//!
111//! Specifically, `ThinVec` will trivially relocate its contents whenever it needs to reallocate its
112//! buffer to change its capacity. This is the default reallocation strategy for nsTArray, and is
113//! suitable for the vast majority of types. Just be aware of this limitation!
114//!
115//! ## Auto Arrays Are Dangerous
116//!
117//! `ThinVec` has *some* support for handling auto arrays which store their buffer on the stack,
118//! but this isn't well tested.
119//!
120//! Regardless of how much support we provide, Rust won't be aware of the buffer's limited lifetime,
121//! so standard auto array safety caveats apply about returning/storing them! `ThinVec` won't ever
122//! produce an auto array on its own, so this is only an issue for transferring an nsTArray into
123//! Rust.
124//!
125//! ## Other Issues
126//!
127//! Standard FFI caveats also apply:
128//!
129//! * Rust is more strict about POD types being initialized (use MaybeUninit if you must)
130//! * `ThinVec<T>` has no idea if the C++ version of `T` has move/copy/assign/delete overloads
131//! * `nsTArray<T>` has no idea if the Rust version of `T` has a Drop/Clone impl
132//! * C++ can do all sorts of unsound things that Rust can't catch
133//! * C++ and Rust don't agree on how zero-sized/empty types should be handled
134//!
135//! The gecko-ffi feature will not work if you aren't linking with code that has nsTArray
136//! defined. Specifically, we must share the symbol for nsTArray's empty singleton. You will get
137//! linking errors if that isn't defined.
138//!
139//! The gecko-ffi feature also limits `ThinVec` to the legacy behaviors of nsTArray. Most notably,
140//! nsTArray has a maximum capacity of i32::MAX (~2.1 billion items). Probably not an issue.
141//! Probably.
142//!
143//! [pinned]: https://doc.rust-lang.org/std/pin/index.html
144
145#![cfg_attr(not(feature = "std"), no_std)]
146#![cfg_attr(feature = "unstable", feature(trusted_len))]
147#![cfg_attr(feature = "unstable", feature(dropck_eyepatch))]
148#![allow(clippy::comparison_chain, clippy::missing_safety_doc)]
149
150extern crate alloc;
151
152use alloc::alloc::*;
153use alloc::{boxed::Box, vec::Vec};
154use core::borrow::*;
155use core::cmp::*;
156use core::convert::TryFrom;
157use core::convert::TryInto;
158use core::hash::*;
159use core::iter::FromIterator;
160use core::marker::PhantomData;
161use core::ops::Bound;
162use core::ops::{Deref, DerefMut, RangeBounds};
163use core::ptr::NonNull;
164use core::slice::Iter;
165use core::{fmt, mem, ops, ptr, slice};
166
167use impl_details::*;
168
169#[cfg(feature = "malloc_size_of")]
170use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
171
172// modules: a simple way to cfg a whole bunch of impl details at once
173
174#[cfg(not(feature = "gecko-ffi"))]
175mod impl_details {
176 pub type SizeType = usize;
177 // for ZSTs, store the length in the the NonNull<T> as a NonZero<usize>,
178 // the length is thus off by one and can only reach usize::MAX - 1
179 pub const MAX_CAP: usize = usize::MAX - 1;
180
181 #[inline(always)]
182 pub fn assert_size(x: usize) -> SizeType {
183 x
184 }
185
186 #[inline(always)]
187 pub fn pack_capacity_and_auto(cap: SizeType, auto: bool) -> SizeType {
188 debug_assert!(!auto);
189 cap
190 }
191
192 #[inline(always)]
193 pub fn unpack_capacity(cap: SizeType) -> usize {
194 cap
195 }
196
197 #[inline(always)]
198 pub fn is_auto(_: SizeType) -> bool {
199 false
200 }
201}
202
203#[cfg(feature = "gecko-ffi")]
204mod impl_details {
205 // Support for briding a gecko nsTArray verbatim into a ThinVec.
206 //
207 // `ThinVec` can't see copy/move/delete implementations
208 // from C++
209 //
210 // The actual layout of an nsTArray is:
211 //
212 // ```cpp
213 // struct {
214 // uint32_t mLength;
215 // uint32_t mCapacity: 31;
216 // uint32_t mIsAutoArray : 1;
217 // }
218 // ```
219 //
220 // Rust doesn't natively support bit-fields, so we manually mask
221 // and shift the bit. When the "auto" bit is set, the header and buffer
222 // are actually on the stack, meaning the `ThinVec` pointer-to-header
223 // is essentially an "owned borrow", and therefore dangerous to handle.
224 // There are no safety guards for this situation.
225 //
226 // On little-endian platforms, the auto bit will be the high-bit of
227 // our capacity u32. On big-endian platforms, it will be the low bit.
228 // Hence we need some platform-specific CFGs for the necessary masking/shifting.
229 //
230 // Handling the auto bit mostly just means not freeing/reallocating the buffer.
231
232 pub type SizeType = u32;
233
234 pub const MAX_CAP: usize = i32::MAX as usize;
235
236 // See kAutoTArrayHeaderOffset
237 pub const AUTO_ARRAY_HEADER_OFFSET: usize = 8;
238
239 // Little endian: the auto bit is the high bit, and the capacity is
240 // verbatim. So we just need to mask off the high bit. Note that
241 // this masking is unnecessary when packing, because assert_size
242 // guards against the high bit being set.
243 #[cfg(target_endian = "little")]
244 pub fn unpack_capacity(cap: SizeType) -> usize {
245 (cap as usize) & !(1 << 31)
246 }
247 #[cfg(target_endian = "little")]
248 pub fn is_auto(cap: SizeType) -> bool {
249 (cap & (1 << 31)) != 0
250 }
251 #[cfg(target_endian = "little")]
252 pub fn pack_capacity_and_auto(cap: SizeType, auto: bool) -> SizeType {
253 cap | ((auto as SizeType) << 31)
254 }
255
256 // Big endian: the auto bit is the low bit, and the capacity is
257 // shifted up one bit. Masking out the auto bit is unnecessary,
258 // as rust shifts always shift in 0's for unsigned integers.
259 #[cfg(target_endian = "big")]
260 pub fn unpack_capacity(cap: SizeType) -> usize {
261 (cap >> 1) as usize
262 }
263 #[cfg(target_endian = "big")]
264 pub fn is_auto(cap: SizeType) -> bool {
265 (cap & 1) != 0
266 }
267 #[cfg(target_endian = "big")]
268 pub fn pack_capacity_and_auto(cap: SizeType, auto: bool) -> SizeType {
269 (cap << 1) | (auto as SizeType)
270 }
271
272 #[inline]
273 pub fn assert_size(x: usize) -> SizeType {
274 if x > MAX_CAP as usize {
275 panic!("nsTArray size may not exceed the capacity of a 32-bit sized int");
276 }
277 x as SizeType
278 }
279}
280
281#[cold]
282fn capacity_overflow() -> ! {
283 panic!("capacity overflow")
284}
285
286trait UnwrapCapOverflow<T> {
287 fn unwrap_cap_overflow(self) -> T;
288}
289
290impl<T> UnwrapCapOverflow<T> for Option<T> {
291 fn unwrap_cap_overflow(self) -> T {
292 match self {
293 Some(val) => val,
294 None => capacity_overflow(),
295 }
296 }
297}
298
299impl<T, E> UnwrapCapOverflow<T> for Result<T, E> {
300 fn unwrap_cap_overflow(self) -> T {
301 match self {
302 Ok(val) => val,
303 Err(_) => capacity_overflow(),
304 }
305 }
306}
307
308// The header of a ThinVec.
309//
310// The _cap can be a bitfield, so use accessors to avoid trouble.
311//
312// In "real" gecko-ffi mode, the empty singleton will be aligned
313// to 8 by gecko. But in tests we have to provide the singleton
314// ourselves, and Rust makes it hard to "just" align a static.
315// To avoid messing around with a wrapper type around the
316// singleton *just* for tests, we just force all headers to be
317// aligned to 8 in this weird "zombie" gecko mode.
318//
319// This shouldn't affect runtime layout (padding), but it will
320// result in us asking the allocator to needlessly overalign
321// non-empty ThinVecs containing align < 8 types in
322// zombie-mode, but not in "real" geck-ffi mode. Minor.
323#[cfg_attr(all(feature = "gecko-ffi", any(test, miri)), repr(align(8)))]
324#[repr(C)]
325struct Header {
326 _len: SizeType,
327 _cap: SizeType,
328}
329
330impl Header {
331 #[inline]
332 #[allow(clippy::unnecessary_cast)]
333 fn len(&self) -> usize {
334 self._len as usize
335 }
336
337 #[inline]
338 fn set_len(&mut self, len: usize) {
339 self._len = assert_size(len);
340 }
341
342 fn cap(&self) -> usize {
343 unpack_capacity(self._cap)
344 }
345
346 fn set_cap_and_auto(&mut self, cap: usize, is_auto: bool) {
347 // debug check that our packing is working
348 debug_assert_eq!(
349 unpack_capacity(pack_capacity_and_auto(cap as SizeType, is_auto)),
350 cap
351 );
352 self._cap = pack_capacity_and_auto(assert_size(cap), is_auto);
353 }
354
355 #[inline]
356 fn is_auto(&self) -> bool {
357 is_auto(self._cap)
358 }
359}
360
361/// Singleton that all empty collections share.
362/// Note: can't store non-zero ZSTs, we allocate in that case. We could
363/// optimize everything to not do that (basically, make ptr == len and branch
364/// on size == 0 in every method), but it's a bunch of work for something that
365/// doesn't matter much.
366#[cfg(any(not(feature = "gecko-ffi"), test, miri))]
367static EMPTY_HEADER: Header = Header { _len: 0, _cap: 0 };
368
369#[cfg(all(feature = "gecko-ffi", not(test), not(miri)))]
370unsafe extern "C" {
371 #[link_name = "sEmptyTArrayHeader"]
372 static EMPTY_HEADER: Header;
373}
374
375// Utils for computing layouts of allocations
376
377/// Gets the size necessary to allocate a `ThinVec<T>` with the give capacity.
378///
379/// # Panics
380///
381/// This will panic if isize::MAX is overflowed at any point.
382fn alloc_size<T>(cap: usize) -> usize {
383 // Compute "real" header size with pointer math
384 //
385 // We turn everything into isizes here so that we can catch isize::MAX overflow,
386 // we never want to allow allocations larger than that!
387 let header_size = mem::size_of::<Header>() as isize;
388 let padding = padding::<T>() as isize;
389
390 let data_size = if mem::size_of::<T>() == 0 {
391 // If we're allocating an array for ZSTs we need a header/padding but no actual
392 // space for items, so we don't care about the capacity that was requested!
393 0
394 } else {
395 let cap: isize = cap.try_into().unwrap_cap_overflow();
396 let elem_size = mem::size_of::<T>() as isize;
397 elem_size.checked_mul(cap).unwrap_cap_overflow()
398 };
399
400 let final_size = data_size
401 .checked_add(header_size + padding)
402 .unwrap_cap_overflow();
403
404 // Ok now we can turn it back into a usize (don't need to worry about negatives)
405 final_size as usize
406}
407
408/// Gets the padding necessary for the array of a `ThinVec<T>`
409const fn padding<T>() -> usize {
410 let alloc_align = alloc_align::<T>();
411 let header_size = mem::size_of::<Header>();
412 if cfg!(feature = "gecko-ffi") {
413 assert!(
414 mem::size_of::<T>() != 0,
415 "ThinVec<T> cannot bridge to nsTArray<T> when T is zero-sized"
416 );
417 assert!(
418 header_size >= alloc_align,
419 "nsTArray does not handle alignment above the header size correctly",
420 );
421 }
422 alloc_align.saturating_sub(header_size)
423}
424
425/// Gets the align necessary to allocate a `ThinVec<T>`
426const fn alloc_align<T>() -> usize {
427 if mem::align_of::<T>() > mem::align_of::<Header>() {
428 return mem::align_of::<T>();
429 }
430 mem::align_of::<Header>()
431}
432
433/// Gets the layout necessary to allocate a `ThinVec<T>`
434///
435/// # Panics
436///
437/// Panics if the required size overflows `isize::MAX` when rounded up to the required alignment.
438fn layout<T>(cap: usize) -> Layout {
439 Layout::from_size_align(alloc_size::<T>(cap), alloc_align::<T>())
440 .ok()
441 .unwrap_cap_overflow()
442}
443
444/// Allocates a header (and array) for a `ThinVec<T>` with the given capacity.
445///
446/// # Panics
447///
448/// Panics if the required size overflows `isize::MAX` when rounded up to the required alignment.
449fn header_with_capacity<T>(cap: usize, is_auto: bool) -> NonNull<Header> {
450 debug_assert!(cap > 0);
451 unsafe {
452 let layout = layout::<T>(cap);
453 let header = alloc(layout) as *mut Header;
454
455 if header.is_null() {
456 handle_alloc_error(layout)
457 }
458
459 ptr::write(
460 header,
461 Header {
462 _len: 0,
463 _cap: if mem::size_of::<T>() == 0 {
464 // "Infinite" capacity for zero-sized types:
465 MAX_CAP as SizeType
466 } else {
467 pack_capacity_and_auto(assert_size(cap), is_auto)
468 },
469 },
470 );
471
472 NonNull::new_unchecked(header)
473 }
474}
475
476/// # Safety
477///
478/// len must be != 0, this uses the `NonNull` to store a length, so the length must be stored offset by one.
479/// This function expect the len to be already shifted
480#[inline(always)]
481const unsafe fn len_to_ptr_unchecked<T: Sized>(len: usize) -> NonNull<T> {
482 use core::num::NonZeroUsize;
483 debug_assert!(len != 0);
484 // NonNull::without_provenance polyfill
485 unsafe { mem::transmute(NonZeroUsize::new_unchecked(len)) }
486}
487
488/// See the crate's top level documentation for a description of this type.
489#[repr(C)]
490pub struct ThinVec<T> {
491 ptr: NonNull<Header>,
492 boo: PhantomData<T>,
493}
494
495unsafe impl<T: Sync> Sync for ThinVec<T> {}
496unsafe impl<T: Send> Send for ThinVec<T> {}
497
498/// Creates a `ThinVec` containing the arguments.
499///
500// A hack to avoid linking problems with `cargo test --features=gecko-ffi`.
501#[cfg_attr(not(feature = "gecko-ffi"), doc = "```")]
502#[cfg_attr(feature = "gecko-ffi", doc = "```ignore")]
503/// #[macro_use] extern crate thin_vec;
504///
505/// fn main() {
506/// let v = thin_vec![1, 2, 3];
507/// assert_eq!(v.len(), 3);
508/// assert_eq!(v[0], 1);
509/// assert_eq!(v[1], 2);
510/// assert_eq!(v[2], 3);
511///
512/// let v = thin_vec![1; 3];
513/// assert_eq!(v, [1, 1, 1]);
514/// }
515/// ```
516#[macro_export]
517macro_rules! thin_vec {
518 (@UNIT $($t:tt)*) => (());
519
520 ($elem:expr; $n:expr) => ({
521 let mut vec = $crate::ThinVec::new();
522 vec.resize($n, $elem);
523 vec
524 });
525 () => {$crate::ThinVec::new()};
526 ($($x:expr),*) => ({
527 let len = [$($crate::thin_vec!(@UNIT $x)),*].len();
528 let mut vec = $crate::ThinVec::with_capacity(len);
529 $(vec.push($x);)*
530 vec
531 });
532 ($($x:expr,)*) => ($crate::thin_vec![$($x),*]);
533}
534
535impl<T> ThinVec<T> {
536 /// Return true if we can use ZST optimizations
537 #[inline(always)]
538 const fn is_zst() -> bool {
539 size_of::<T>() == 0 && !cfg!(feature = "gecko-ffi")
540 }
541
542 /// Creates a new empty ThinVec.
543 ///
544 /// This will not allocate.
545 pub const fn new() -> ThinVec<T> {
546 // See the comment in with_capacity().
547 let _ = padding::<T>();
548
549 if Self::is_zst() {
550 unsafe {
551 ThinVec {
552 ptr: len_to_ptr_unchecked(1),
553 boo: PhantomData,
554 }
555 }
556 } else {
557 unsafe {
558 ThinVec {
559 ptr: NonNull::new_unchecked(&EMPTY_HEADER as *const Header as *mut Header),
560 boo: PhantomData,
561 }
562 }
563 }
564 }
565
566 /// Constructs a new, empty `ThinVec<T>` with at least the specified capacity.
567 ///
568 /// The vector will be able to hold at least `capacity` elements without
569 /// reallocating. This method is allowed to allocate for more elements than
570 /// `capacity`. If `capacity` is 0, the vector will not allocate.
571 ///
572 /// It is important to note that although the returned vector has the
573 /// minimum *capacity* specified, the vector will have a zero *length*.
574 ///
575 /// If it is important to know the exact allocated capacity of a `ThinVec`,
576 /// always use the [`capacity`] method after construction.
577 ///
578 /// **NOTE**: unlike `Vec`, `ThinVec` **MUST** allocate once to keep track of non-zero
579 /// lengths. As such, we cannot provide the same guarantees about ThinVecs
580 /// of ZSTs not allocating. However the allocation never needs to be resized
581 /// to add more ZSTs, since the underlying array is still length 0.
582 ///
583 /// [Capacity and reallocation]: #capacity-and-reallocation
584 /// [`capacity`]: Vec::capacity
585 ///
586 /// # Panics
587 ///
588 /// Panics if the new capacity exceeds `isize::MAX` bytes.
589 ///
590 /// # Examples
591 ///
592 /// ```
593 /// use thin_vec::ThinVec;
594 ///
595 /// let mut vec = ThinVec::with_capacity(10);
596 ///
597 /// // The vector contains no items, even though it has capacity for more
598 /// assert_eq!(vec.len(), 0);
599 /// assert!(vec.capacity() >= 10);
600 ///
601 /// // These are all done without reallocating...
602 /// for i in 0..10 {
603 /// vec.push(i);
604 /// }
605 /// assert_eq!(vec.len(), 10);
606 /// assert!(vec.capacity() >= 10);
607 ///
608 /// // ...but this may make the vector reallocate
609 /// vec.push(11);
610 /// assert_eq!(vec.len(), 11);
611 /// assert!(vec.capacity() >= 11);
612 ///
613 /// # #[cfg(not(feature = "gecko-ffi"))] {
614 /// // A vector of a zero-sized type will always over-allocate, since no
615 /// // space is needed to store the actual elements.
616 /// // Note this is only true **without** the gecko-ffi feature!
617 /// let vec_units = ThinVec::<()>::with_capacity(10);
618 /// assert_eq!(vec_units.capacity(), usize::MAX - 1);
619 /// # }
620 /// ```
621 pub fn with_capacity(cap: usize) -> Self {
622 // `padding` contains ~static assertions against types that are
623 // incompatible with the current feature flags. We also call it to
624 // invoke these assertions when getting a pointer to the `ThinVec`
625 // contents, but since we also get a pointer to the contents in the
626 // `Drop` impl, tripping an assertion along that code path causes a
627 // double panic. We duplicate the assertion here so that it is
628 // testable,
629 let _ = padding::<T>();
630
631 if Self::is_zst() {
632 unsafe {
633 return ThinVec {
634 ptr: len_to_ptr_unchecked(1),
635 boo: PhantomData,
636 };
637 }
638 }
639
640 if cap == 0 {
641 return Self::new();
642 }
643 ThinVec {
644 ptr: header_with_capacity::<T>(cap, false),
645 boo: PhantomData,
646 }
647 }
648
649 // Accessor conveniences
650
651 /// # Safety
652 ///
653 /// must have Self::is_zst() == false
654 unsafe fn ptr(&self) -> *mut Header {
655 debug_assert!(!Self::is_zst());
656 self.ptr.as_ptr()
657 }
658
659 /// # Safety
660 ///
661 /// must have Self::is_zst() == false
662 unsafe fn header(&self) -> &Header {
663 debug_assert!(!Self::is_zst());
664 unsafe { self.ptr.as_ref() }
665 }
666
667 fn data_raw(&self) -> *mut T {
668 if Self::is_zst() {
669 return ptr::dangling_mut();
670 }
671
672 // `padding` contains ~static assertions against types that are
673 // incompatible with the current feature flags. Even if we don't
674 // care about its result, we should always call it before getting
675 // a data pointer to guard against invalid types!
676 let padding = padding::<T>();
677
678 // Although we ensure the data array is aligned when we allocate,
679 // we can't do that with the empty singleton. So when it might not
680 // be properly aligned, we substitute in the NonNull::dangling
681 // which *is* aligned.
682 //
683 // To minimize dynamic branches on `cap` for all accesses
684 // to the data, we include this guard which should only involve
685 // compile-time constants. Ideally this should result in the branch
686 // only be included for types with excessive alignment.
687 let empty_header_is_aligned = if cfg!(feature = "gecko-ffi") {
688 // in gecko-ffi mode `padding` will ensure this under
689 // the assumption that the header has size 8 and the
690 // static empty singleton is aligned to 8.
691 true
692 } else {
693 // In non-gecko-ffi mode, the empty singleton is just
694 // naturally aligned to the Header. If the Header is at
695 // least as aligned as T *and* the padding would have
696 // been 0, then one-past-the-end of the empty singleton
697 // *is* a valid data pointer and we can remove the
698 // `dangling` special case.
699 mem::align_of::<Header>() >= mem::align_of::<T>() && padding == 0
700 };
701
702 unsafe {
703 if !empty_header_is_aligned && self.header().cap() == 0 {
704 NonNull::dangling().as_ptr()
705 } else {
706 // This could technically result in overflow, but padding
707 // would have to be absurdly large for this to occur.
708 let header_size = mem::size_of::<Header>();
709 let ptr = self.ptr.as_ptr() as *mut u8;
710 ptr.add(header_size + padding) as *mut T
711 }
712 }
713 }
714
715 /// # Safety
716 ///
717 /// This is unsafe when the header is EMPTY_HEADER or when T is a ZST.
718 unsafe fn header_mut(&mut self) -> &mut Header {
719 debug_assert!(!self.is_singleton());
720 debug_assert!(!Self::is_zst());
721 unsafe { &mut *self.ptr() }
722 }
723
724 /// Returns the number of elements in the vector, also referred to
725 /// as its 'length'.
726 ///
727 /// # Examples
728 ///
729 /// ```
730 /// use thin_vec::thin_vec;
731 ///
732 /// let a = thin_vec![1, 2, 3];
733 /// assert_eq!(a.len(), 3);
734 /// ```
735 pub fn len(&self) -> usize {
736 if Self::is_zst() {
737 (self.ptr.as_ptr() as usize) - 1
738 } else {
739 unsafe { self.header().len() }
740 }
741 }
742
743 /// Returns `true` if the vector contains no elements.
744 ///
745 /// # Examples
746 ///
747 /// ```
748 /// use thin_vec::ThinVec;
749 ///
750 /// let mut v = ThinVec::new();
751 /// assert!(v.is_empty());
752 ///
753 /// v.push(1);
754 /// assert!(!v.is_empty());
755 /// ```
756 pub fn is_empty(&self) -> bool {
757 self.len() == 0
758 }
759
760 /// Returns the number of elements the vector can hold without
761 /// reallocating.
762 ///
763 /// # Examples
764 ///
765 /// ```
766 /// use thin_vec::ThinVec;
767 ///
768 /// let vec: ThinVec<i32> = ThinVec::with_capacity(10);
769 /// assert_eq!(vec.capacity(), 10);
770 /// ```
771 pub fn capacity(&self) -> usize {
772 if Self::is_zst() {
773 MAX_CAP
774 } else {
775 unsafe { self.header().cap() }
776 }
777 }
778
779 /// Returns `true` if the vector has the capacity to hold any element.
780 pub fn has_capacity(&self) -> bool {
781 !self.is_singleton()
782 }
783
784 /// Forces the length of the vector to `new_len`.
785 ///
786 /// This is a low-level operation that maintains none of the normal
787 /// invariants of the type. Normally changing the length of a vector
788 /// is done using one of the safe operations instead, such as
789 /// [`truncate`], [`resize`], [`extend`], or [`clear`].
790 ///
791 /// [`truncate`]: ThinVec::truncate
792 /// [`resize`]: ThinVec::resize
793 /// [`extend`]: ThinVec::extend
794 /// [`clear`]: ThinVec::clear
795 ///
796 /// # Safety
797 ///
798 /// - `new_len` must be less than or equal to [`capacity()`].
799 /// - The elements at `old_len..new_len` must be initialized.
800 ///
801 /// [`capacity()`]: ThinVec::capacity
802 ///
803 /// # Examples
804 ///
805 /// This method can be useful for situations in which the vector
806 /// is serving as a buffer for other code, particularly over FFI:
807 ///
808 /// ```no_run
809 /// use thin_vec::ThinVec;
810 ///
811 /// # // This is just a minimal skeleton for the doc example;
812 /// # // don't use this as a starting point for a real library.
813 /// # pub struct StreamWrapper { strm: *mut std::ffi::c_void }
814 /// # const Z_OK: i32 = 0;
815 /// # unsafe extern "C" {
816 /// # fn deflateGetDictionary(
817 /// # strm: *mut std::ffi::c_void,
818 /// # dictionary: *mut u8,
819 /// # dictLength: *mut usize,
820 /// # ) -> i32;
821 /// # }
822 /// # impl StreamWrapper {
823 /// pub fn get_dictionary(&self) -> Option<ThinVec<u8>> {
824 /// // Per the FFI method's docs, "32768 bytes is always enough".
825 /// let mut dict = ThinVec::with_capacity(32_768);
826 /// let mut dict_length = 0;
827 /// // SAFETY: When `deflateGetDictionary` returns `Z_OK`, it holds that:
828 /// // 1. `dict_length` elements were initialized.
829 /// // 2. `dict_length` <= the capacity (32_768)
830 /// // which makes `set_len` safe to call.
831 /// unsafe {
832 /// // Make the FFI call...
833 /// let r = deflateGetDictionary(self.strm, dict.as_mut_ptr(), &mut dict_length);
834 /// if r == Z_OK {
835 /// // ...and update the length to what was initialized.
836 /// dict.set_len(dict_length);
837 /// Some(dict)
838 /// } else {
839 /// None
840 /// }
841 /// }
842 /// }
843 /// # }
844 /// ```
845 ///
846 /// While the following example is sound, there is a memory leak since
847 /// the inner vectors were not freed prior to the `set_len` call:
848 ///
849 /// ```no_run
850 /// use thin_vec::thin_vec;
851 ///
852 /// let mut vec = thin_vec![thin_vec![1, 0, 0],
853 /// thin_vec![0, 1, 0],
854 /// thin_vec![0, 0, 1]];
855 /// // SAFETY:
856 /// // 1. `old_len..0` is empty so no elements need to be initialized.
857 /// // 2. `0 <= capacity` always holds whatever `capacity` is.
858 /// unsafe {
859 /// vec.set_len(0);
860 /// }
861 /// ```
862 ///
863 /// Normally, here, one would use [`clear`] instead to correctly drop
864 /// the contents and thus not leak memory.
865 pub unsafe fn set_len(&mut self, len: usize) {
866 if self.is_singleton() {
867 // A prerequisite of `Vec::set_len` is that `new_len` must be
868 // less than or equal to capacity(). The same applies here.
869 debug_assert!(len == 0, "invalid set_len({}) on empty ThinVec", len);
870 } else {
871 unsafe { self.set_len_non_singleton(len) }
872 }
873 }
874
875 /// For internal use only, when setting the length and it's known that T is a ZST.
876 /// # Safety
877 /// - This is unsafe when T is not a ZST.
878 /// - len must be < usize::MAX
879 #[inline]
880 unsafe fn set_len_zst(&mut self, len: usize) {
881 debug_assert!(Self::is_zst());
882 debug_assert!(
883 len <= MAX_CAP,
884 "invalid set_len(usize::MAX) on ZST ThinVec (max cap is usize::MAX - 1)"
885 );
886 unsafe { self.ptr = len_to_ptr_unchecked(len + 1) }
887 }
888
889 /// For internal use only, when setting the length and it's known that the header is owned.
890 /// # Safety
891 /// This is unsafe when the header is EMPTY_HEADER or when T is a ZST.
892 #[inline]
893 unsafe fn set_header_len(&mut self, len: usize) {
894 unsafe { self.header_mut().set_len(len) }
895 }
896
897 /// For internal use only, when setting the length and it's known to be the non-singleton or T is a ZST.
898 /// # Safety
899 /// This is unsafe when the header is EMPTY_HEADER.
900 #[inline(always)]
901 unsafe fn set_len_non_singleton(&mut self, len: usize) {
902 debug_assert!(!self.is_singleton());
903 if Self::is_zst() {
904 unsafe {
905 self.set_len_zst(len);
906 }
907 } else {
908 unsafe { self.set_header_len(len) }
909 }
910 }
911
912 /// Appends an element to the back of a collection.
913 ///
914 /// # Panics
915 ///
916 /// Panics if the new capacity exceeds `isize::MAX` bytes.
917 ///
918 /// # Examples
919 ///
920 /// ```
921 /// use thin_vec::thin_vec;
922 ///
923 /// let mut vec = thin_vec![1, 2];
924 /// vec.push(3);
925 /// assert_eq!(vec, [1, 2, 3]);
926 /// ```
927 pub fn push(&mut self, val: T) {
928 let old_len = self.len();
929 if old_len == self.capacity() {
930 self.reserve(1);
931 }
932 unsafe {
933 // SAFETY: reserve() ensures sufficient capacity.
934 self.push_unchecked(val);
935 }
936 }
937
938 /// Appends an element to the back like `push`,
939 /// but assumes that sufficient capacity has already been reserved, i.e.
940 /// `len() < capacity()`.
941 ///
942 /// # Safety
943 ///
944 /// - Capacity must be reserved in advance such that `capacity() > len()`.
945 #[inline]
946 unsafe fn push_unchecked(&mut self, val: T) {
947 let old_len = self.len();
948 debug_assert!(old_len < self.capacity());
949 unsafe {
950 ptr::write(self.data_raw().add(old_len), val);
951 // SAFETY: capacity > len >= 0, so capacity != 0, so this is not a singleton.
952 self.set_len_non_singleton(old_len + 1);
953 }
954 }
955
956 /// Removes the last element from a vector and returns it, or [`None`] if it
957 /// is empty.
958 ///
959 /// # Examples
960 ///
961 /// ```
962 /// use thin_vec::thin_vec;
963 ///
964 /// let mut vec = thin_vec![1, 2, 3];
965 /// assert_eq!(vec.pop(), Some(3));
966 /// assert_eq!(vec, [1, 2]);
967 /// ```
968 pub fn pop(&mut self) -> Option<T> {
969 let old_len = self.len();
970 if old_len == 0 {
971 return None;
972 }
973
974 unsafe {
975 self.set_len_non_singleton(old_len - 1);
976 Some(ptr::read(self.data_raw().add(old_len - 1)))
977 }
978 }
979
980 /// Inserts an element at position `index` within the vector, shifting all
981 /// elements after it to the right.
982 ///
983 /// # Panics
984 ///
985 /// Panics if `index > len`.
986 ///
987 /// # Examples
988 ///
989 /// ```
990 /// use thin_vec::thin_vec;
991 ///
992 /// let mut vec = thin_vec![1, 2, 3];
993 /// vec.insert(1, 4);
994 /// assert_eq!(vec, [1, 4, 2, 3]);
995 /// vec.insert(4, 5);
996 /// assert_eq!(vec, [1, 4, 2, 3, 5]);
997 /// ```
998 pub fn insert(&mut self, idx: usize, elem: T) {
999 let old_len = self.len();
1000
1001 assert!(idx <= old_len, "Index out of bounds");
1002 if old_len == self.capacity() {
1003 self.reserve(1);
1004 }
1005 unsafe {
1006 let ptr = self.data_raw();
1007 ptr::copy(ptr.add(idx), ptr.add(idx + 1), old_len - idx);
1008 ptr::write(ptr.add(idx), elem);
1009 self.set_header_len(old_len + 1);
1010 }
1011 }
1012
1013 /// Removes and returns the element at position `index` within the vector,
1014 /// shifting all elements after it to the left.
1015 ///
1016 /// Note: Because this shifts over the remaining elements, it has a
1017 /// worst-case performance of *O*(*n*). If you don't need the order of elements
1018 /// to be preserved, use [`swap_remove`] instead. If you'd like to remove
1019 /// elements from the beginning of the `ThinVec`, consider using `std::collections::VecDeque`.
1020 ///
1021 /// [`swap_remove`]: ThinVec::swap_remove
1022 ///
1023 /// # Panics
1024 ///
1025 /// Panics if `index` is out of bounds.
1026 ///
1027 /// # Examples
1028 ///
1029 /// ```
1030 /// use thin_vec::thin_vec;
1031 ///
1032 /// let mut v = thin_vec![1, 2, 3];
1033 /// assert_eq!(v.remove(1), 2);
1034 /// assert_eq!(v, [1, 3]);
1035 /// ```
1036 pub fn remove(&mut self, idx: usize) -> T {
1037 let old_len = self.len();
1038
1039 assert!(idx < old_len, "Index out of bounds");
1040
1041 unsafe {
1042 self.set_len_non_singleton(old_len - 1);
1043 let ptr = self.data_raw();
1044 let val = ptr::read(self.data_raw().add(idx));
1045 ptr::copy(ptr.add(idx + 1), ptr.add(idx), old_len - idx - 1);
1046 val
1047 }
1048 }
1049
1050 /// Removes an element from the vector and returns it.
1051 ///
1052 /// The removed element is replaced by the last element of the vector.
1053 ///
1054 /// This does not preserve ordering, but is *O*(1).
1055 /// If you need to preserve the element order, use [`remove`] instead.
1056 ///
1057 /// [`remove`]: ThinVec::remove
1058 ///
1059 /// # Panics
1060 ///
1061 /// Panics if `index` is out of bounds.
1062 ///
1063 /// # Examples
1064 ///
1065 /// ```
1066 /// use thin_vec::thin_vec;
1067 ///
1068 /// let mut v = thin_vec!["foo", "bar", "baz", "qux"];
1069 ///
1070 /// assert_eq!(v.swap_remove(1), "bar");
1071 /// assert_eq!(v, ["foo", "qux", "baz"]);
1072 ///
1073 /// assert_eq!(v.swap_remove(0), "foo");
1074 /// assert_eq!(v, ["baz", "qux"]);
1075 /// ```
1076 pub fn swap_remove(&mut self, idx: usize) -> T {
1077 let old_len = self.len();
1078
1079 assert!(idx < old_len, "Index out of bounds");
1080
1081 unsafe {
1082 let ptr = self.data_raw();
1083 ptr::swap(ptr.add(idx), ptr.add(old_len - 1));
1084 self.set_len_non_singleton(old_len - 1);
1085 ptr::read(ptr.add(old_len - 1))
1086 }
1087 }
1088
1089 /// Shortens the vector, keeping the first `len` elements and dropping
1090 /// the rest.
1091 ///
1092 /// If `len` is greater than the vector's current length, this has no
1093 /// effect.
1094 ///
1095 /// The [`drain`] method can emulate `truncate`, but causes the excess
1096 /// elements to be returned instead of dropped.
1097 ///
1098 /// Note that this method has no effect on the allocated capacity
1099 /// of the vector.
1100 ///
1101 /// # Examples
1102 ///
1103 /// Truncating a five element vector to two elements:
1104 ///
1105 /// ```
1106 /// use thin_vec::thin_vec;
1107 ///
1108 /// let mut vec = thin_vec![1, 2, 3, 4, 5];
1109 /// vec.truncate(2);
1110 /// assert_eq!(vec, [1, 2]);
1111 /// ```
1112 ///
1113 /// No truncation occurs when `len` is greater than the vector's current
1114 /// length:
1115 ///
1116 /// ```
1117 /// use thin_vec::thin_vec;
1118 ///
1119 /// let mut vec = thin_vec![1, 2, 3];
1120 /// vec.truncate(8);
1121 /// assert_eq!(vec, [1, 2, 3]);
1122 /// ```
1123 ///
1124 /// Truncating when `len == 0` is equivalent to calling the [`clear`]
1125 /// method.
1126 ///
1127 /// ```
1128 /// use thin_vec::thin_vec;
1129 ///
1130 /// let mut vec = thin_vec![1, 2, 3];
1131 /// vec.truncate(0);
1132 /// assert_eq!(vec, []);
1133 /// ```
1134 ///
1135 /// [`clear`]: ThinVec::clear
1136 /// [`drain`]: ThinVec::drain
1137 pub fn truncate(&mut self, len: usize) {
1138 unsafe {
1139 // drop any extra elements
1140 while len < self.len() {
1141 // decrement len before the drop_in_place(), so a panic on Drop
1142 // doesn't re-drop the just-failed value.
1143 let new_len = self.len() - 1;
1144 self.set_len_non_singleton(new_len);
1145 let ptr = self.data_raw().add(new_len);
1146 ptr::drop_in_place(ptr);
1147 }
1148 }
1149 }
1150
1151 /// Clears the vector, removing all values.
1152 ///
1153 /// Note that this method has no effect on the allocated capacity
1154 /// of the vector.
1155 ///
1156 /// # Examples
1157 ///
1158 /// ```
1159 /// use thin_vec::thin_vec;
1160 ///
1161 /// let mut v = thin_vec![1, 2, 3];
1162 /// v.clear();
1163 /// assert!(v.is_empty());
1164 /// ```
1165 pub fn clear(&mut self) {
1166 unsafe {
1167 // Decrement len even in the case of a panic.
1168 struct DropGuard<'a, T>(&'a mut ThinVec<T>);
1169 impl<T> Drop for DropGuard<'_, T> {
1170 fn drop(&mut self) {
1171 unsafe {
1172 // Could be the singleton.
1173 self.0.set_len(0);
1174 }
1175 }
1176 }
1177 let guard = DropGuard(self);
1178 ptr::drop_in_place(&mut guard.0[..]);
1179 }
1180 }
1181
1182 /// Extracts a slice containing the entire vector.
1183 ///
1184 /// Equivalent to `&s[..]`.
1185 ///
1186 /// # Examples
1187 ///
1188 /// ```
1189 /// use thin_vec::thin_vec;
1190 /// use std::io::{self, Write};
1191 /// let buffer = thin_vec![1, 2, 3, 5, 8];
1192 /// io::sink().write(buffer.as_slice()).unwrap();
1193 /// ```
1194 pub fn as_slice(&self) -> &[T] {
1195 unsafe { slice::from_raw_parts(self.data_raw(), self.len()) }
1196 }
1197
1198 /// Extracts a mutable slice of the entire vector.
1199 ///
1200 /// Equivalent to `&mut s[..]`.
1201 ///
1202 /// # Examples
1203 ///
1204 /// ```
1205 /// use thin_vec::thin_vec;
1206 /// use std::io::{self, Read};
1207 /// let mut buffer = vec![0; 3];
1208 /// io::repeat(0b101).read_exact(buffer.as_mut_slice()).unwrap();
1209 /// ```
1210 pub fn as_mut_slice(&mut self) -> &mut [T] {
1211 unsafe { slice::from_raw_parts_mut(self.data_raw(), self.len()) }
1212 }
1213
1214 /// Reserve capacity for at least `additional` more elements to be inserted.
1215 ///
1216 /// May reserve more space than requested, to avoid frequent reallocations.
1217 ///
1218 /// Panics if the new capacity overflows `usize`.
1219 ///
1220 /// Re-allocates only if `self.capacity() < self.len() + additional`.
1221 #[cfg(not(feature = "gecko-ffi"))]
1222 pub fn reserve(&mut self, additional: usize) {
1223 let len = self.len();
1224 let old_cap = self.capacity();
1225 let min_cap = len.checked_add(additional).unwrap_cap_overflow();
1226 if min_cap <= old_cap {
1227 return;
1228 }
1229 // only way to get here is if min_cap == usize::MAX, which we can't handle.
1230 if Self::is_zst() {
1231 capacity_overflow();
1232 }
1233 // Ensure the new capacity is at least double, to guarantee exponential growth.
1234 let double_cap = if old_cap == 0 {
1235 // skip to 4 because tiny ThinVecs are dumb; but not if that would cause overflow
1236 if mem::size_of::<T>() > (!0) / 8 { 1 } else { 4 }
1237 } else {
1238 old_cap.saturating_mul(2)
1239 };
1240 let new_cap = max(min_cap, double_cap);
1241 unsafe {
1242 self.reallocate(new_cap);
1243 }
1244 }
1245
1246 /// Reserve capacity for at least `additional` more elements to be inserted.
1247 ///
1248 /// This method mimics the growth algorithm used by the C++ implementation
1249 /// of nsTArray.
1250 #[cfg(feature = "gecko-ffi")]
1251 pub fn reserve(&mut self, additional: usize) {
1252 let elem_size = mem::size_of::<T>();
1253
1254 let len = self.len();
1255 let old_cap = self.capacity();
1256 let min_cap = len.checked_add(additional).unwrap_cap_overflow();
1257 if min_cap <= old_cap {
1258 return;
1259 }
1260 // The growth logic can't handle zero-sized types, so we have to exit
1261 // early here.
1262 if elem_size == 0 {
1263 unsafe {
1264 self.reallocate(min_cap);
1265 }
1266 return;
1267 }
1268
1269 let min_cap_bytes = assert_size(min_cap)
1270 .checked_mul(assert_size(elem_size))
1271 .and_then(|x| x.checked_add(assert_size(mem::size_of::<Header>())))
1272 .unwrap();
1273
1274 // Perform some checked arithmetic to ensure all of the numbers we
1275 // compute will end up in range.
1276 let will_fit = min_cap_bytes.checked_mul(2).is_some();
1277 if !will_fit {
1278 panic!("Exceeded maximum nsTArray size");
1279 }
1280
1281 const SLOW_GROWTH_THRESHOLD: usize = 8 * 1024 * 1024;
1282
1283 let bytes = if min_cap > SLOW_GROWTH_THRESHOLD {
1284 // Grow by a minimum of 1.125x
1285 let old_cap_bytes = old_cap * elem_size + mem::size_of::<Header>();
1286 let min_growth = old_cap_bytes + (old_cap_bytes >> 3);
1287 let growth = max(min_growth, min_cap_bytes as usize);
1288
1289 // Round up to the next megabyte.
1290 const MB: usize = 1 << 20;
1291 MB * ((growth + MB - 1) / MB)
1292 } else {
1293 // Try to allocate backing buffers in powers of two.
1294 min_cap_bytes.next_power_of_two() as usize
1295 };
1296
1297 let cap = (bytes - core::mem::size_of::<Header>()) / elem_size;
1298 unsafe {
1299 self.reallocate(cap);
1300 }
1301 }
1302
1303 /// Reserves the minimum capacity for `additional` more elements to be inserted.
1304 ///
1305 /// Panics if the new capacity overflows `usize`.
1306 ///
1307 /// Re-allocates only if `self.capacity() < self.len() + additional`.
1308 pub fn reserve_exact(&mut self, additional: usize) {
1309 let new_cap = self.len().checked_add(additional).unwrap_cap_overflow();
1310 let old_cap = self.capacity();
1311 if new_cap > old_cap {
1312 // only way to get here is if new_cap == usize::MAX, which we can't handle.
1313 if Self::is_zst() {
1314 capacity_overflow()
1315 }
1316 unsafe {
1317 self.reallocate(new_cap);
1318 }
1319 }
1320 }
1321
1322 /// Shrinks the capacity of the vector as much as possible.
1323 ///
1324 /// It will drop down as close as possible to the length but the allocator
1325 /// may still inform the vector that there is space for a few more elements.
1326 ///
1327 /// # Examples
1328 ///
1329 /// ```
1330 /// use thin_vec::ThinVec;
1331 ///
1332 /// let mut vec = ThinVec::with_capacity(10);
1333 /// vec.extend([1, 2, 3]);
1334 /// assert_eq!(vec.capacity(), 10);
1335 /// vec.shrink_to_fit();
1336 /// assert!(vec.capacity() >= 3);
1337 /// ```
1338 pub fn shrink_to_fit(&mut self) {
1339 if Self::is_zst() {
1340 return;
1341 }
1342 let old_cap = self.capacity();
1343 let new_cap = self.len();
1344 if new_cap >= old_cap {
1345 return;
1346 }
1347 #[cfg(feature = "gecko-ffi")]
1348 unsafe {
1349 let stack_buf = self.auto_array_header_mut();
1350 if !stack_buf.is_null() && (*stack_buf).cap() >= new_cap {
1351 // Try to switch to our auto-buffer.
1352 if stack_buf == self.ptr.as_ptr() {
1353 return;
1354 }
1355 stack_buf
1356 .add(1)
1357 .cast::<T>()
1358 .copy_from_nonoverlapping(self.data_raw(), new_cap);
1359 dealloc(self.ptr() as *mut u8, layout::<T>(old_cap));
1360 self.ptr = NonNull::new_unchecked(stack_buf);
1361 self.ptr.as_mut().set_len(new_cap);
1362 return;
1363 }
1364 }
1365 if new_cap == 0 {
1366 *self = ThinVec::new();
1367 } else {
1368 unsafe {
1369 self.reallocate(new_cap);
1370 }
1371 }
1372 }
1373
1374 /// Retains only the elements specified by the predicate.
1375 ///
1376 /// In other words, remove all elements `e` such that `f(&e)` returns `false`.
1377 /// This method operates in place and preserves the order of the retained
1378 /// elements.
1379 ///
1380 /// # Examples
1381 ///
1382 // A hack to avoid linking problems with `cargo test --features=gecko-ffi`.
1383 #[cfg_attr(not(feature = "gecko-ffi"), doc = "```")]
1384 #[cfg_attr(feature = "gecko-ffi", doc = "```ignore")]
1385 /// # #[macro_use] extern crate thin_vec;
1386 /// # fn main() {
1387 /// let mut vec = thin_vec![1, 2, 3, 4];
1388 /// vec.retain(|&x| x%2 == 0);
1389 /// assert_eq!(vec, [2, 4]);
1390 /// # }
1391 /// ```
1392 pub fn retain<F>(&mut self, mut f: F)
1393 where
1394 F: FnMut(&T) -> bool,
1395 {
1396 self.retain_mut(|x| f(&*x));
1397 }
1398
1399 /// Retains only the elements specified by the predicate, passing a mutable reference to it.
1400 ///
1401 /// In other words, remove all elements `e` such that `f(&mut e)` returns `false`.
1402 /// This method operates in place and preserves the order of the retained
1403 /// elements.
1404 ///
1405 /// # Examples
1406 ///
1407 // A hack to avoid linking problems with `cargo test --features=gecko-ffi`.
1408 #[cfg_attr(not(feature = "gecko-ffi"), doc = "```")]
1409 #[cfg_attr(feature = "gecko-ffi", doc = "```ignore")]
1410 /// # #[macro_use] extern crate thin_vec;
1411 /// # fn main() {
1412 /// let mut vec = thin_vec![1, 2, 3, 4, 5];
1413 /// vec.retain_mut(|x| {
1414 /// *x += 1;
1415 /// (*x)%2 == 0
1416 /// });
1417 /// assert_eq!(vec, [2, 4, 6]);
1418 /// # }
1419 /// ```
1420 pub fn retain_mut<F>(&mut self, mut f: F)
1421 where
1422 F: FnMut(&mut T) -> bool,
1423 {
1424 let len = self.len();
1425 let mut del = 0;
1426 {
1427 let v = &mut self[..];
1428
1429 for i in 0..len {
1430 if !f(&mut v[i]) {
1431 del += 1;
1432 } else if del > 0 {
1433 v.swap(i - del, i);
1434 }
1435 }
1436 }
1437 if del > 0 {
1438 self.truncate(len - del);
1439 }
1440 }
1441
1442 /// Removes consecutive elements in the vector that resolve to the same key.
1443 ///
1444 /// If the vector is sorted, this removes all duplicates.
1445 ///
1446 /// # Examples
1447 ///
1448 // A hack to avoid linking problems with `cargo test --features=gecko-ffi`.
1449 #[cfg_attr(not(feature = "gecko-ffi"), doc = "```")]
1450 #[cfg_attr(feature = "gecko-ffi", doc = "```ignore")]
1451 /// # #[macro_use] extern crate thin_vec;
1452 /// # fn main() {
1453 /// let mut vec = thin_vec![10, 20, 21, 30, 20];
1454 ///
1455 /// vec.dedup_by_key(|i| *i / 10);
1456 ///
1457 /// assert_eq!(vec, [10, 20, 30, 20]);
1458 /// # }
1459 /// ```
1460 pub fn dedup_by_key<F, K>(&mut self, mut key: F)
1461 where
1462 F: FnMut(&mut T) -> K,
1463 K: PartialEq<K>,
1464 {
1465 self.dedup_by(|a, b| key(a) == key(b))
1466 }
1467
1468 /// Removes consecutive elements in the vector according to a predicate.
1469 ///
1470 /// The `same_bucket` function is passed references to two elements from the vector, and
1471 /// returns `true` if the elements compare equal, or `false` if they do not. Only the first
1472 /// of adjacent equal items is kept.
1473 ///
1474 /// If the vector is sorted, this removes all duplicates.
1475 ///
1476 /// # Examples
1477 ///
1478 // A hack to avoid linking problems with `cargo test --features=gecko-ffi`.
1479 #[cfg_attr(not(feature = "gecko-ffi"), doc = "```")]
1480 #[cfg_attr(feature = "gecko-ffi", doc = "```ignore")]
1481 /// # #[macro_use] extern crate thin_vec;
1482 /// # fn main() {
1483 /// let mut vec = thin_vec!["foo", "bar", "Bar", "baz", "bar"];
1484 ///
1485 /// vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
1486 ///
1487 /// assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
1488 /// # }
1489 /// ```
1490 #[allow(clippy::swap_ptr_to_ref)]
1491 pub fn dedup_by<F>(&mut self, mut same_bucket: F)
1492 where
1493 F: FnMut(&mut T, &mut T) -> bool,
1494 {
1495 // See the comments in `Vec::dedup` for a detailed explanation of this code.
1496 unsafe {
1497 let ln = self.len();
1498 if ln <= 1 {
1499 return;
1500 }
1501
1502 // Avoid bounds checks by using raw pointers.
1503 let p = self.as_mut_ptr();
1504 let mut r: usize = 1;
1505 let mut w: usize = 1;
1506
1507 while r < ln {
1508 let p_r = p.add(r);
1509 let p_wm1 = p.add(w - 1);
1510 if !same_bucket(&mut *p_r, &mut *p_wm1) {
1511 if r != w {
1512 let p_w = p_wm1.add(1);
1513 mem::swap(&mut *p_r, &mut *p_w);
1514 }
1515 w += 1;
1516 }
1517 r += 1;
1518 }
1519
1520 self.truncate(w);
1521 }
1522 }
1523
1524 /// Splits the collection into two at the given index.
1525 ///
1526 /// Returns a newly allocated vector containing the elements in the range
1527 /// `[at, len)`. After the call, the original vector will be left containing
1528 /// the elements `[0, at)` with its previous capacity unchanged.
1529 ///
1530 /// # Panics
1531 ///
1532 /// Panics if `at > len`.
1533 ///
1534 /// # Examples
1535 ///
1536 /// ```
1537 /// use thin_vec::thin_vec;
1538 ///
1539 /// let mut vec = thin_vec![1, 2, 3];
1540 /// let vec2 = vec.split_off(1);
1541 /// assert_eq!(vec, [1]);
1542 /// assert_eq!(vec2, [2, 3]);
1543 /// ```
1544 pub fn split_off(&mut self, at: usize) -> ThinVec<T> {
1545 let old_len = self.len();
1546 let new_vec_len = old_len - at;
1547
1548 assert!(at <= old_len, "Index out of bounds");
1549
1550 unsafe {
1551 let mut new_vec = ThinVec::with_capacity(new_vec_len);
1552
1553 ptr::copy_nonoverlapping(self.data_raw().add(at), new_vec.data_raw(), new_vec_len);
1554
1555 new_vec.set_len(new_vec_len); // could be the singleton
1556 self.set_len(at); // could be the singleton
1557
1558 new_vec
1559 }
1560 }
1561
1562 /// Moves all the elements of `other` into `self`, leaving `other` empty.
1563 ///
1564 /// # Panics
1565 ///
1566 /// Panics if the new capacity exceeds `isize::MAX` bytes.
1567 ///
1568 /// # Examples
1569 ///
1570 /// ```
1571 /// use thin_vec::thin_vec;
1572 ///
1573 /// let mut vec = thin_vec![1, 2, 3];
1574 /// let mut vec2 = thin_vec![4, 5, 6];
1575 /// vec.append(&mut vec2);
1576 /// assert_eq!(vec, [1, 2, 3, 4, 5, 6]);
1577 /// assert_eq!(vec2, []);
1578 /// ```
1579 pub fn append(&mut self, other: &mut ThinVec<T>) {
1580 self.extend(other.drain(..))
1581 }
1582
1583 /// Removes the specified range from the vector in bulk, returning all
1584 /// removed elements as an iterator. If the iterator is dropped before
1585 /// being fully consumed, it drops the remaining removed elements.
1586 ///
1587 /// The returned iterator keeps a mutable borrow on the vector to optimize
1588 /// its implementation.
1589 ///
1590 /// # Panics
1591 ///
1592 /// Panics if the starting point is greater than the end point or if
1593 /// the end point is greater than the length of the vector.
1594 ///
1595 /// # Leaking
1596 ///
1597 /// If the returned iterator goes out of scope without being dropped (due to
1598 /// [`mem::forget`], for example), the vector may have lost and leaked
1599 /// elements arbitrarily, including elements outside the range.
1600 ///
1601 /// # Examples
1602 ///
1603 /// ```
1604 /// use thin_vec::{ThinVec, thin_vec};
1605 ///
1606 /// let mut v = thin_vec![1, 2, 3];
1607 /// let u: ThinVec<_> = v.drain(1..).collect();
1608 /// assert_eq!(v, &[1]);
1609 /// assert_eq!(u, &[2, 3]);
1610 ///
1611 /// // A full range clears the vector, like `clear()` does
1612 /// v.drain(..);
1613 /// assert_eq!(v, &[]);
1614 /// ```
1615 pub fn drain<R>(&mut self, range: R) -> Drain<'_, T>
1616 where
1617 R: RangeBounds<usize>,
1618 {
1619 // See comments in the Drain struct itself for details on this
1620 let len = self.len();
1621 let start = match range.start_bound() {
1622 Bound::Included(&n) => n,
1623 Bound::Excluded(&n) => n + 1,
1624 Bound::Unbounded => 0,
1625 };
1626 let end = match range.end_bound() {
1627 Bound::Included(&n) => n + 1,
1628 Bound::Excluded(&n) => n,
1629 Bound::Unbounded => len,
1630 };
1631 assert!(start <= end);
1632 assert!(end <= len);
1633
1634 unsafe {
1635 // Set our length to the start bound
1636 self.set_len(start); // could be the singleton
1637
1638 let iter = slice::from_raw_parts(self.data_raw().add(start), end - start).iter();
1639
1640 Drain {
1641 iter,
1642 vec: NonNull::from(self),
1643 end,
1644 tail: len - end,
1645 }
1646 }
1647 }
1648
1649 /// Creates a splicing iterator that replaces the specified range in the vector
1650 /// with the given `replace_with` iterator and yields the removed items.
1651 /// `replace_with` does not need to be the same length as `range`.
1652 ///
1653 /// `range` is removed even if the iterator is not consumed until the end.
1654 ///
1655 /// It is unspecified how many elements are removed from the vector
1656 /// if the `Splice` value is leaked.
1657 ///
1658 /// The input iterator `replace_with` is only consumed when the `Splice` value is dropped.
1659 ///
1660 /// This is optimal if:
1661 ///
1662 /// * The tail (elements in the vector after `range`) is empty,
1663 /// * or `replace_with` yields fewer or equal elements than `range`’s length
1664 /// * or the lower bound of its `size_hint()` is exact.
1665 ///
1666 /// Otherwise, a temporary vector is allocated and the tail is moved twice.
1667 ///
1668 /// # Panics
1669 ///
1670 /// Panics if the starting point is greater than the end point or if
1671 /// the end point is greater than the length of the vector.
1672 ///
1673 /// # Examples
1674 ///
1675 /// ```
1676 /// use thin_vec::{ThinVec, thin_vec};
1677 ///
1678 /// let mut v = thin_vec![1, 2, 3, 4];
1679 /// let new = [7, 8, 9];
1680 /// let u: ThinVec<_> = v.splice(1..3, new).collect();
1681 /// assert_eq!(v, &[1, 7, 8, 9, 4]);
1682 /// assert_eq!(u, &[2, 3]);
1683 /// ```
1684 #[inline]
1685 pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter>
1686 where
1687 R: RangeBounds<usize>,
1688 I: IntoIterator<Item = T>,
1689 {
1690 Splice {
1691 drain: self.drain(range),
1692 replace_with: replace_with.into_iter(),
1693 }
1694 }
1695
1696 /// Creates an iterator which uses a closure to determine if an element should be removed.
1697 ///
1698 /// If the closure returns true, then the element is removed and yielded.
1699 /// If the closure returns false, the element will remain in the vector and will not be yielded
1700 /// by the iterator.
1701 ///
1702 /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating
1703 /// or the iteration short-circuits, then the remaining elements will be retained.
1704 /// Use [`ThinVec::retain`] with a negated predicate if you do not need the returned iterator.
1705 ///
1706 /// Using this method is equivalent to the following code:
1707 ///
1708 /// ```
1709 /// # use thin_vec::{ThinVec, thin_vec};
1710 /// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 };
1711 /// # let mut vec = thin_vec![1, 2, 3, 4, 5, 6];
1712 /// let mut i = 0;
1713 /// while i < vec.len() {
1714 /// if some_predicate(&mut vec[i]) {
1715 /// let val = vec.remove(i);
1716 /// // your code here
1717 /// } else {
1718 /// i += 1;
1719 /// }
1720 /// }
1721 ///
1722 /// # assert_eq!(vec, thin_vec![1, 4, 5]);
1723 /// ```
1724 ///
1725 /// But `extract_if` is easier to use. `extract_if` is also more efficient,
1726 /// because it can backshift the elements of the array in bulk.
1727 ///
1728 /// Note that `extract_if` also lets you mutate every element in the filter closure,
1729 /// regardless of whether you choose to keep or remove it.
1730 ///
1731 /// # Examples
1732 ///
1733 /// Splitting an array into evens and odds, reusing the original allocation:
1734 ///
1735 /// ```
1736 /// use thin_vec::{ThinVec, thin_vec};
1737 ///
1738 /// let mut numbers = thin_vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15];
1739 ///
1740 /// let evens = numbers.extract_if(.., |x| *x % 2 == 0).collect::<ThinVec<_>>();
1741 /// let odds = numbers;
1742 ///
1743 /// assert_eq!(evens, thin_vec![2, 4, 6, 8, 14]);
1744 /// assert_eq!(odds, thin_vec![1, 3, 5, 9, 11, 13, 15]);
1745 /// ```
1746 pub fn extract_if<F, R: RangeBounds<usize>>(
1747 &mut self,
1748 range: R,
1749 filter: F,
1750 ) -> ExtractIf<'_, T, F>
1751 where
1752 F: FnMut(&mut T) -> bool,
1753 {
1754 // Copy of https://github.com/rust-lang/rust/blob/ee361e8fca1c30e13e7a31cc82b64c045339d3a8/library/core/src/slice/index.rs#L37
1755 fn slice_index_fail(start: usize, end: usize, len: usize) -> ! {
1756 if start > len {
1757 panic!(
1758 "range start index {} out of range for slice of length {}",
1759 start, len
1760 )
1761 }
1762
1763 if end > len {
1764 panic!(
1765 "range end index {} out of range for slice of length {}",
1766 end, len
1767 )
1768 }
1769
1770 if start > end {
1771 panic!("slice index starts at {} but ends at {}", start, end)
1772 }
1773
1774 // Only reachable if the range was a `RangeInclusive` or a
1775 // `RangeToInclusive`, with `end == len`.
1776 panic!(
1777 "range end index {} out of range for slice of length {}",
1778 end, len
1779 )
1780 }
1781
1782 // Backport of https://github.com/rust-lang/rust/blob/ee361e8fca1c30e13e7a31cc82b64c045339d3a8/library/core/src/slice/index.rs#L855
1783 pub fn slice_range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize>
1784 where
1785 R: ops::RangeBounds<usize>,
1786 {
1787 let len = bounds.end;
1788
1789 let end = match range.end_bound() {
1790 ops::Bound::Included(&end) if end >= len => slice_index_fail(0, end, len),
1791 // Cannot overflow because `end < len` implies `end < usize::MAX`.
1792 ops::Bound::Included(&end) => end + 1,
1793
1794 ops::Bound::Excluded(&end) if end > len => slice_index_fail(0, end, len),
1795 ops::Bound::Excluded(&end) => end,
1796 ops::Bound::Unbounded => len,
1797 };
1798
1799 let start = match range.start_bound() {
1800 ops::Bound::Excluded(&start) if start >= end => slice_index_fail(start, end, len),
1801 // Cannot overflow because `start < end` implies `start < usize::MAX`.
1802 ops::Bound::Excluded(&start) => start + 1,
1803
1804 ops::Bound::Included(&start) if start > end => slice_index_fail(start, end, len),
1805 ops::Bound::Included(&start) => start,
1806
1807 ops::Bound::Unbounded => 0,
1808 };
1809
1810 ops::Range { start, end }
1811 }
1812
1813 let old_len = self.len();
1814 let ops::Range { start, end } = slice_range(range, ..old_len);
1815
1816 // Guard against the vec getting leaked (leak amplification)
1817 unsafe {
1818 self.set_len(0);
1819 }
1820 ExtractIf {
1821 vec: self,
1822 idx: start,
1823 del: 0,
1824 end,
1825 old_len,
1826 pred: filter,
1827 }
1828 }
1829
1830 /// Resize the buffer and update its capacity, without changing the length.
1831 /// Unsafe because it can cause length to be greater than capacity.
1832 ///
1833 /// # Safety
1834 ///
1835 /// Must not be called if Self::is_zst()
1836 unsafe fn reallocate(&mut self, new_cap: usize) {
1837 debug_assert!(new_cap > 0);
1838 debug_assert!(!Self::is_zst());
1839 if self.has_allocation() {
1840 let old_cap = self.capacity();
1841 unsafe {
1842 let ptr = realloc(
1843 self.ptr() as *mut u8,
1844 layout::<T>(old_cap),
1845 alloc_size::<T>(new_cap),
1846 ) as *mut Header;
1847 if ptr.is_null() {
1848 handle_alloc_error(layout::<T>(new_cap))
1849 }
1850 (*ptr).set_cap_and_auto(new_cap, (*ptr).is_auto());
1851 self.ptr = NonNull::new_unchecked(ptr);
1852 }
1853 } else {
1854 let mut new_header = header_with_capacity::<T>(new_cap, self.is_auto_array());
1855
1856 // If we get here and have a non-zero len, then we must be handling
1857 // a gecko auto array, and we have items in a stack buffer. We shouldn't
1858 // free it, but we should memcopy the contents out of it and mark it as empty.
1859 //
1860 // T is assumed to be trivially relocatable, as this is ~required
1861 // for Rust compatibility anyway. Furthermore, we assume C++ won't try
1862 // to unconditionally destroy the contents of the stack allocated buffer
1863 // (i.e. it's obfuscated behind a union).
1864 //
1865 // In effect, we are partially reimplementing the auto array move constructor
1866 // by leaving behind a valid empty instance.
1867 let len = self.len();
1868 if cfg!(feature = "gecko-ffi") && len > 0 {
1869 unsafe {
1870 new_header
1871 .as_ptr()
1872 .add(1)
1873 .cast::<T>()
1874 .copy_from_nonoverlapping(self.data_raw(), len);
1875 self.set_header_len(0);
1876 new_header.as_mut().set_len(len);
1877 }
1878 }
1879
1880 self.ptr = new_header;
1881 }
1882 }
1883
1884 #[inline]
1885 #[allow(unused_unsafe)]
1886 fn is_singleton(&self) -> bool {
1887 if Self::is_zst() {
1888 false
1889 } else {
1890 unsafe { self.ptr.as_ptr() as *const Header == &EMPTY_HEADER }
1891 }
1892 }
1893
1894 #[cfg(feature = "gecko-ffi")]
1895 #[inline]
1896 fn auto_array_header_mut(&mut self) -> *mut Header {
1897 if !self.is_auto_array() {
1898 return ptr::null_mut();
1899 }
1900 unsafe { (self as *mut Self).byte_add(AUTO_ARRAY_HEADER_OFFSET) as *mut Header }
1901 }
1902
1903 #[cfg(feature = "gecko-ffi")]
1904 #[inline]
1905 fn auto_array_header(&self) -> *const Header {
1906 if !self.is_auto_array() {
1907 return ptr::null_mut();
1908 }
1909 unsafe { (self as *const Self).byte_add(AUTO_ARRAY_HEADER_OFFSET) as *const Header }
1910 }
1911
1912 #[inline]
1913 fn is_auto_array(&self) -> bool {
1914 unsafe { self.ptr.as_ref().is_auto() }
1915 }
1916
1917 #[inline]
1918 fn uses_stack_allocated_buffer(&self) -> bool {
1919 #[cfg(feature = "gecko-ffi")]
1920 return self.auto_array_header() == self.ptr.as_ptr();
1921 #[cfg(not(feature = "gecko-ffi"))]
1922 return false;
1923 }
1924
1925 #[inline]
1926 fn has_allocation(&self) -> bool {
1927 !Self::is_zst() && !self.is_singleton() && !self.uses_stack_allocated_buffer()
1928 }
1929}
1930
1931impl<T: Clone> ThinVec<T> {
1932 /// Resizes the `Vec` in-place so that `len()` is equal to `new_len`.
1933 ///
1934 /// If `new_len` is greater than `len()`, the `Vec` is extended by the
1935 /// difference, with each additional slot filled with `value`.
1936 /// If `new_len` is less than `len()`, the `Vec` is simply truncated.
1937 ///
1938 /// # Examples
1939 ///
1940 // A hack to avoid linking problems with `cargo test --features=gecko-ffi`.
1941 #[cfg_attr(not(feature = "gecko-ffi"), doc = "```")]
1942 #[cfg_attr(feature = "gecko-ffi", doc = "```ignore")]
1943 /// # #[macro_use] extern crate thin_vec;
1944 /// # fn main() {
1945 /// let mut vec = thin_vec!["hello"];
1946 /// vec.resize(3, "world");
1947 /// assert_eq!(vec, ["hello", "world", "world"]);
1948 ///
1949 /// let mut vec = thin_vec![1, 2, 3, 4];
1950 /// vec.resize(2, 0);
1951 /// assert_eq!(vec, [1, 2]);
1952 /// # }
1953 /// ```
1954 pub fn resize(&mut self, new_len: usize, value: T) {
1955 let old_len = self.len();
1956
1957 if new_len > old_len {
1958 let additional = new_len - old_len;
1959 self.reserve(additional);
1960 for _ in 1..additional {
1961 self.push(value.clone());
1962 }
1963 // We can write the last element directly without cloning needlessly
1964 if additional > 0 {
1965 self.push(value);
1966 }
1967 } else if new_len < old_len {
1968 self.truncate(new_len);
1969 }
1970 }
1971
1972 /// Clones and appends all elements in a slice to the `ThinVec`.
1973 ///
1974 /// Iterates over the slice `other`, clones each element, and then appends
1975 /// it to this `ThinVec`. The `other` slice is traversed in-order.
1976 ///
1977 /// Note that this function is same as [`extend`] except that it is
1978 /// specialized to work with slices instead. If and when Rust gets
1979 /// specialization this function will likely be deprecated (but still
1980 /// available).
1981 ///
1982 /// # Examples
1983 ///
1984 /// ```
1985 /// use thin_vec::thin_vec;
1986 ///
1987 /// let mut vec = thin_vec![1];
1988 /// vec.extend_from_slice(&[2, 3, 4]);
1989 /// assert_eq!(vec, [1, 2, 3, 4]);
1990 /// ```
1991 ///
1992 /// [`extend`]: ThinVec::extend
1993 pub fn extend_from_slice(&mut self, other: &[T]) {
1994 self.extend(other.iter().cloned())
1995 }
1996}
1997
1998impl<T: PartialEq> ThinVec<T> {
1999 /// Removes consecutive repeated elements in the vector.
2000 ///
2001 /// If the vector is sorted, this removes all duplicates.
2002 ///
2003 /// # Examples
2004 ///
2005 // A hack to avoid linking problems with `cargo test --features=gecko-ffi`.
2006 #[cfg_attr(not(feature = "gecko-ffi"), doc = "```")]
2007 #[cfg_attr(feature = "gecko-ffi", doc = "```ignore")]
2008 /// # #[macro_use] extern crate thin_vec;
2009 /// # fn main() {
2010 /// let mut vec = thin_vec![1, 2, 2, 3, 2];
2011 ///
2012 /// vec.dedup();
2013 ///
2014 /// assert_eq!(vec, [1, 2, 3, 2]);
2015 /// # }
2016 /// ```
2017 pub fn dedup(&mut self) {
2018 self.dedup_by(|a, b| a == b)
2019 }
2020}
2021
2022#[cold]
2023#[inline(never)]
2024fn drop_non_singleton<T>(this: &mut ThinVec<T>) {
2025 unsafe {
2026 ptr::drop_in_place(&mut this[..]);
2027
2028 if this.uses_stack_allocated_buffer() {
2029 return;
2030 }
2031
2032 dealloc(this.ptr() as *mut u8, layout::<T>(this.capacity()))
2033 }
2034}
2035
2036/// # Safety
2037///
2038/// This function drop and deallocates the inner values of the `ThinVec`,
2039/// invariants are therefore broken and the value must be considered dropped and should not be accessed again.
2040#[inline]
2041unsafe fn drop_thin_vec<T>(this: &mut ThinVec<T>) {
2042 if ThinVec::<T>::is_zst() {
2043 unsafe {
2044 ptr::drop_in_place(&mut this[..]);
2045 }
2046 } else if !this.is_singleton() {
2047 drop_non_singleton(this);
2048 }
2049}
2050
2051#[cfg(not(feature = "unstable"))]
2052impl<T> Drop for ThinVec<T> {
2053 #[inline]
2054 fn drop(&mut self) {
2055 unsafe {
2056 drop_thin_vec(self);
2057 }
2058 }
2059}
2060
2061#[cfg(feature = "unstable")]
2062unsafe impl<#[may_dangle] T> Drop for ThinVec<T> {
2063 #[inline]
2064 fn drop(&mut self) {
2065 unsafe {
2066 drop_thin_vec(self);
2067 }
2068 }
2069}
2070
2071impl<T> Deref for ThinVec<T> {
2072 type Target = [T];
2073
2074 fn deref(&self) -> &[T] {
2075 self.as_slice()
2076 }
2077}
2078
2079impl<T> DerefMut for ThinVec<T> {
2080 fn deref_mut(&mut self) -> &mut [T] {
2081 self.as_mut_slice()
2082 }
2083}
2084
2085impl<T> Borrow<[T]> for ThinVec<T> {
2086 fn borrow(&self) -> &[T] {
2087 self.as_slice()
2088 }
2089}
2090
2091impl<T> BorrowMut<[T]> for ThinVec<T> {
2092 fn borrow_mut(&mut self) -> &mut [T] {
2093 self.as_mut_slice()
2094 }
2095}
2096
2097impl<T> AsRef<[T]> for ThinVec<T> {
2098 fn as_ref(&self) -> &[T] {
2099 self.as_slice()
2100 }
2101}
2102
2103impl<T> Extend<T> for ThinVec<T> {
2104 #[inline]
2105 fn extend<I>(&mut self, iter: I)
2106 where
2107 I: IntoIterator<Item = T>,
2108 {
2109 let mut iter = iter.into_iter();
2110 let hint = iter.size_hint().0;
2111 if hint > 0 {
2112 self.reserve(hint);
2113 for x in iter.by_ref().take(hint) {
2114 // SAFETY: `reserve(hint)` ensures the next `hint` calls of `push_unchecked`
2115 // have sufficient capacity.
2116 unsafe {
2117 self.push_unchecked(x);
2118 }
2119 }
2120 }
2121
2122 // if the hint underestimated the iterator length,
2123 // push the remaining items with capacity check each time.
2124 for x in iter {
2125 self.push(x);
2126 }
2127 }
2128}
2129
2130impl<T: fmt::Debug> fmt::Debug for ThinVec<T> {
2131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2132 fmt::Debug::fmt(&**self, f)
2133 }
2134}
2135
2136impl<T> Hash for ThinVec<T>
2137where
2138 T: Hash,
2139{
2140 fn hash<H>(&self, state: &mut H)
2141 where
2142 H: Hasher,
2143 {
2144 self[..].hash(state);
2145 }
2146}
2147
2148impl<T> PartialOrd for ThinVec<T>
2149where
2150 T: PartialOrd,
2151{
2152 #[inline]
2153 fn partial_cmp(&self, other: &ThinVec<T>) -> Option<Ordering> {
2154 self[..].partial_cmp(&other[..])
2155 }
2156}
2157
2158impl<T> Ord for ThinVec<T>
2159where
2160 T: Ord,
2161{
2162 #[inline]
2163 fn cmp(&self, other: &ThinVec<T>) -> Ordering {
2164 self[..].cmp(&other[..])
2165 }
2166}
2167
2168impl<A, B> PartialEq<ThinVec<B>> for ThinVec<A>
2169where
2170 A: PartialEq<B>,
2171{
2172 #[inline]
2173 fn eq(&self, other: &ThinVec<B>) -> bool {
2174 self[..] == other[..]
2175 }
2176}
2177
2178impl<A, B> PartialEq<Vec<B>> for ThinVec<A>
2179where
2180 A: PartialEq<B>,
2181{
2182 #[inline]
2183 fn eq(&self, other: &Vec<B>) -> bool {
2184 self[..] == other[..]
2185 }
2186}
2187
2188impl<A, B> PartialEq<[B]> for ThinVec<A>
2189where
2190 A: PartialEq<B>,
2191{
2192 #[inline]
2193 fn eq(&self, other: &[B]) -> bool {
2194 self[..] == other[..]
2195 }
2196}
2197
2198impl<'a, A, B> PartialEq<&'a [B]> for ThinVec<A>
2199where
2200 A: PartialEq<B>,
2201{
2202 #[inline]
2203 fn eq(&self, other: &&'a [B]) -> bool {
2204 self[..] == other[..]
2205 }
2206}
2207
2208// Serde impls based on
2209// https://github.com/bluss/arrayvec/blob/67ec907a98c0f40c4b76066fed3c1af59d35cf6a/src/arrayvec.rs#L1222-L1267
2210#[cfg(feature = "serde")]
2211impl<T: serde::Serialize> serde::Serialize for ThinVec<T> {
2212 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2213 where
2214 S: serde::Serializer,
2215 {
2216 serializer.collect_seq(self.as_slice())
2217 }
2218}
2219
2220#[cfg(feature = "serde")]
2221impl<'de, T: serde::Deserialize<'de>> serde::Deserialize<'de> for ThinVec<T> {
2222 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2223 where
2224 D: serde::Deserializer<'de>,
2225 {
2226 use serde::Deserialize;
2227 use serde::de::{SeqAccess, Visitor};
2228
2229 struct ThinVecVisitor<T>(PhantomData<T>);
2230
2231 impl<'de, T: Deserialize<'de>> Visitor<'de> for ThinVecVisitor<T> {
2232 type Value = ThinVec<T>;
2233
2234 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2235 write!(formatter, "a sequence")
2236 }
2237
2238 fn visit_seq<SA>(self, mut seq: SA) -> Result<Self::Value, SA::Error>
2239 where
2240 SA: SeqAccess<'de>,
2241 {
2242 // Same policy as
2243 // https://github.com/serde-rs/serde/blob/ce0844b9ecc32377b5e4545d759d385a8c46bc6a/serde/src/private/size_hint.rs#L13
2244 let initial_capacity = seq.size_hint().unwrap_or_default().min(4096);
2245 let mut values = ThinVec::<T>::with_capacity(initial_capacity);
2246
2247 while let Some(value) = seq.next_element()? {
2248 values.push(value);
2249 }
2250
2251 Ok(values)
2252 }
2253 }
2254
2255 deserializer.deserialize_seq(ThinVecVisitor::<T>(PhantomData))
2256 }
2257}
2258
2259#[cfg(feature = "malloc_size_of")]
2260impl<T> MallocShallowSizeOf for ThinVec<T> {
2261 fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
2262 if !self.has_allocation() {
2263 // We're not a heap pointer.
2264 return 0;
2265 }
2266
2267 unsafe { ops.malloc_size_of(self.ptr() as _) }
2268 }
2269}
2270
2271#[cfg(feature = "malloc_size_of")]
2272impl<T: MallocSizeOf> MallocSizeOf for ThinVec<T> {
2273 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
2274 let mut n = self.shallow_size_of(ops);
2275 for elem in self.iter() {
2276 n += elem.size_of(ops);
2277 }
2278 n
2279 }
2280}
2281
2282macro_rules! array_impls {
2283 ($($N:expr)*) => {$(
2284 impl<A, B> PartialEq<[B; $N]> for ThinVec<A> where A: PartialEq<B> {
2285 #[inline]
2286 fn eq(&self, other: &[B; $N]) -> bool { self[..] == other[..] }
2287 }
2288
2289 impl<'a, A, B> PartialEq<&'a [B; $N]> for ThinVec<A> where A: PartialEq<B> {
2290 #[inline]
2291 fn eq(&self, other: &&'a [B; $N]) -> bool { self[..] == other[..] }
2292 }
2293 )*}
2294}
2295
2296array_impls! {
2297 0 1 2 3 4 5 6 7 8 9
2298 10 11 12 13 14 15 16 17 18 19
2299 20 21 22 23 24 25 26 27 28 29
2300 30 31 32
2301}
2302
2303impl<T> Eq for ThinVec<T> where T: Eq {}
2304
2305impl<T> IntoIterator for ThinVec<T> {
2306 type Item = T;
2307 type IntoIter = IntoIter<T>;
2308
2309 fn into_iter(self) -> IntoIter<T> {
2310 IntoIter {
2311 vec: self,
2312 start: 0,
2313 }
2314 }
2315}
2316
2317impl<'a, T> IntoIterator for &'a ThinVec<T> {
2318 type Item = &'a T;
2319 type IntoIter = slice::Iter<'a, T>;
2320
2321 fn into_iter(self) -> slice::Iter<'a, T> {
2322 self.iter()
2323 }
2324}
2325
2326impl<'a, T> IntoIterator for &'a mut ThinVec<T> {
2327 type Item = &'a mut T;
2328 type IntoIter = slice::IterMut<'a, T>;
2329
2330 fn into_iter(self) -> slice::IterMut<'a, T> {
2331 self.iter_mut()
2332 }
2333}
2334
2335impl<T> Clone for ThinVec<T>
2336where
2337 T: Clone,
2338{
2339 #[inline]
2340 fn clone(&self) -> ThinVec<T> {
2341 #[cold]
2342 #[inline(never)]
2343 fn clone_non_singleton<T: Clone>(this: &ThinVec<T>) -> ThinVec<T> {
2344 let len = this.len();
2345 let mut new_vec = ThinVec::<T>::with_capacity(len);
2346 let mut data_raw = new_vec.data_raw();
2347 for x in this.iter() {
2348 unsafe {
2349 ptr::write(data_raw, x.clone());
2350 data_raw = data_raw.add(1);
2351 }
2352 }
2353 unsafe {
2354 // `this` is not the singleton, but `new_vec` will be if
2355 // `this` is empty.
2356 new_vec.set_len(len); // could be the singleton
2357 }
2358 new_vec
2359 }
2360
2361 if self.is_singleton() {
2362 ThinVec::new()
2363 } else {
2364 clone_non_singleton(self)
2365 }
2366 }
2367}
2368
2369impl<T> Default for ThinVec<T> {
2370 fn default() -> ThinVec<T> {
2371 ThinVec::new()
2372 }
2373}
2374
2375impl<T> FromIterator<T> for ThinVec<T> {
2376 #[inline]
2377 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> ThinVec<T> {
2378 let mut vec = ThinVec::new();
2379 vec.extend(iter);
2380 vec
2381 }
2382}
2383
2384impl<T: Clone> From<&[T]> for ThinVec<T> {
2385 /// Allocate a `ThinVec<T>` and fill it by cloning `s`'s items.
2386 ///
2387 /// # Examples
2388 ///
2389 /// ```
2390 /// use thin_vec::{ThinVec, thin_vec};
2391 ///
2392 /// assert_eq!(ThinVec::from(&[1, 2, 3][..]), thin_vec![1, 2, 3]);
2393 /// ```
2394 fn from(s: &[T]) -> ThinVec<T> {
2395 s.iter().cloned().collect()
2396 }
2397}
2398
2399impl<T: Clone> From<&mut [T]> for ThinVec<T> {
2400 /// Allocate a `ThinVec<T>` and fill it by cloning `s`'s items.
2401 ///
2402 /// # Examples
2403 ///
2404 /// ```
2405 /// use thin_vec::{ThinVec, thin_vec};
2406 ///
2407 /// assert_eq!(ThinVec::from(&mut [1, 2, 3][..]), thin_vec![1, 2, 3]);
2408 /// ```
2409 fn from(s: &mut [T]) -> ThinVec<T> {
2410 s.iter().cloned().collect()
2411 }
2412}
2413
2414impl<T, const N: usize> From<[T; N]> for ThinVec<T> {
2415 /// Allocate a `ThinVec<T>` and move `s`'s items into it.
2416 ///
2417 /// # Examples
2418 ///
2419 /// ```
2420 /// use thin_vec::{ThinVec, thin_vec};
2421 ///
2422 /// assert_eq!(ThinVec::from([1, 2, 3]), thin_vec![1, 2, 3]);
2423 /// ```
2424 fn from(s: [T; N]) -> ThinVec<T> {
2425 core::iter::IntoIterator::into_iter(s).collect()
2426 }
2427}
2428
2429impl<T> From<Box<[T]>> for ThinVec<T> {
2430 /// Convert a boxed slice into a vector by transferring ownership of
2431 /// the existing heap allocation.
2432 ///
2433 /// **NOTE:** unlike `std`, this must reallocate to change the layout!
2434 ///
2435 /// # Examples
2436 ///
2437 /// ```
2438 /// use thin_vec::{ThinVec, thin_vec};
2439 ///
2440 /// let b: Box<[i32]> = thin_vec![1, 2, 3].into_iter().collect();
2441 /// assert_eq!(ThinVec::from(b), thin_vec![1, 2, 3]);
2442 /// ```
2443 fn from(s: Box<[T]>) -> Self {
2444 // Can just lean on the fact that `Box<[T]>` -> `Vec<T>` is Free.
2445 Vec::from(s).into_iter().collect()
2446 }
2447}
2448
2449impl<T> From<Vec<T>> for ThinVec<T> {
2450 /// Convert a `std::Vec` into a `ThinVec`.
2451 ///
2452 /// **NOTE:** this must reallocate to change the layout!
2453 ///
2454 /// # Examples
2455 ///
2456 /// ```
2457 /// use thin_vec::{ThinVec, thin_vec};
2458 ///
2459 /// let b: Vec<i32> = vec![1, 2, 3];
2460 /// assert_eq!(ThinVec::from(b), thin_vec![1, 2, 3]);
2461 /// ```
2462 fn from(s: Vec<T>) -> Self {
2463 s.into_iter().collect()
2464 }
2465}
2466
2467impl<T> From<ThinVec<T>> for Vec<T> {
2468 /// Convert a `ThinVec` into a `std::Vec`.
2469 ///
2470 /// **NOTE:** this must reallocate to change the layout!
2471 ///
2472 /// # Examples
2473 ///
2474 /// ```
2475 /// use thin_vec::{ThinVec, thin_vec};
2476 ///
2477 /// let b: ThinVec<i32> = thin_vec![1, 2, 3];
2478 /// assert_eq!(Vec::from(b), vec![1, 2, 3]);
2479 /// ```
2480 fn from(s: ThinVec<T>) -> Self {
2481 s.into_iter().collect()
2482 }
2483}
2484
2485impl<T> From<ThinVec<T>> for Box<[T]> {
2486 /// Convert a vector into a boxed slice.
2487 ///
2488 /// If `v` has excess capacity, its items will be moved into a
2489 /// newly-allocated buffer with exactly the right capacity.
2490 ///
2491 /// **NOTE:** unlike `std`, this must reallocate to change the layout!
2492 ///
2493 /// # Examples
2494 ///
2495 /// ```
2496 /// use thin_vec::{ThinVec, thin_vec};
2497 /// assert_eq!(Box::from(thin_vec![1, 2, 3]), thin_vec![1, 2, 3].into_iter().collect());
2498 /// ```
2499 fn from(v: ThinVec<T>) -> Self {
2500 v.into_iter().collect()
2501 }
2502}
2503
2504impl From<&str> for ThinVec<u8> {
2505 /// Allocate a `ThinVec<u8>` and fill it with a UTF-8 string.
2506 ///
2507 /// # Examples
2508 ///
2509 /// ```
2510 /// use thin_vec::{ThinVec, thin_vec};
2511 ///
2512 /// assert_eq!(ThinVec::from("123"), thin_vec![b'1', b'2', b'3']);
2513 /// ```
2514 fn from(s: &str) -> ThinVec<u8> {
2515 From::from(s.as_bytes())
2516 }
2517}
2518
2519impl<T, const N: usize> TryFrom<ThinVec<T>> for [T; N] {
2520 type Error = ThinVec<T>;
2521
2522 /// Gets the entire contents of the `ThinVec<T>` as an array,
2523 /// if its size exactly matches that of the requested array.
2524 ///
2525 /// # Examples
2526 ///
2527 /// ```
2528 /// use thin_vec::{ThinVec, thin_vec};
2529 /// use std::convert::TryInto;
2530 ///
2531 /// assert_eq!(thin_vec![1, 2, 3].try_into(), Ok([1, 2, 3]));
2532 /// assert_eq!(<ThinVec<i32>>::new().try_into(), Ok([]));
2533 /// ```
2534 ///
2535 /// If the length doesn't match, the input comes back in `Err`:
2536 /// ```
2537 /// use thin_vec::{ThinVec, thin_vec};
2538 /// use std::convert::TryInto;
2539 ///
2540 /// let r: Result<[i32; 4], _> = (0..10).collect::<ThinVec<_>>().try_into();
2541 /// assert_eq!(r, Err(thin_vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
2542 /// ```
2543 ///
2544 /// If you're fine with just getting a prefix of the `ThinVec<T>`,
2545 /// you can call [`.truncate(N)`](ThinVec::truncate) first.
2546 /// ```
2547 /// use thin_vec::{ThinVec, thin_vec};
2548 /// use std::convert::TryInto;
2549 ///
2550 /// let mut v = ThinVec::from("hello world");
2551 /// v.sort();
2552 /// v.truncate(2);
2553 /// let [a, b]: [_; 2] = v.try_into().unwrap();
2554 /// assert_eq!(a, b' ');
2555 /// assert_eq!(b, b'd');
2556 /// ```
2557 fn try_from(mut vec: ThinVec<T>) -> Result<[T; N], ThinVec<T>> {
2558 if vec.len() != N {
2559 return Err(vec);
2560 }
2561
2562 // SAFETY: `.set_len(0)` is always sound.
2563 unsafe { vec.set_len(0) };
2564
2565 // SAFETY: A `ThinVec`'s pointer is always aligned properly, and
2566 // the alignment the array needs is the same as the items.
2567 // We checked earlier that we have sufficient items.
2568 // The items will not double-drop as the `set_len`
2569 // tells the `ThinVec` not to also drop them.
2570 let array = unsafe { ptr::read(vec.data_raw() as *const [T; N]) };
2571 Ok(array)
2572 }
2573}
2574
2575/// An iterator that moves out of a vector.
2576///
2577/// This `struct` is created by the [`ThinVec::into_iter`][]
2578/// (provided by the [`IntoIterator`] trait).
2579///
2580/// # Example
2581///
2582/// ```
2583/// use thin_vec::thin_vec;
2584///
2585/// let v = thin_vec![0, 1, 2];
2586/// let iter: thin_vec::IntoIter<_> = v.into_iter();
2587/// ```
2588pub struct IntoIter<T> {
2589 vec: ThinVec<T>,
2590 start: usize,
2591}
2592
2593impl<T> IntoIter<T> {
2594 /// Returns the remaining items of this iterator as a slice.
2595 ///
2596 /// # Examples
2597 ///
2598 /// ```
2599 /// use thin_vec::thin_vec;
2600 ///
2601 /// let vec = thin_vec!['a', 'b', 'c'];
2602 /// let mut into_iter = vec.into_iter();
2603 /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
2604 /// let _ = into_iter.next().unwrap();
2605 /// assert_eq!(into_iter.as_slice(), &['b', 'c']);
2606 /// ```
2607 pub fn as_slice(&self) -> &[T] {
2608 unsafe { slice::from_raw_parts(self.vec.data_raw().add(self.start), self.len()) }
2609 }
2610
2611 /// Returns the remaining items of this iterator as a mutable slice.
2612 ///
2613 /// # Examples
2614 ///
2615 /// ```
2616 /// use thin_vec::thin_vec;
2617 ///
2618 /// let vec = thin_vec!['a', 'b', 'c'];
2619 /// let mut into_iter = vec.into_iter();
2620 /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
2621 /// into_iter.as_mut_slice()[2] = 'z';
2622 /// assert_eq!(into_iter.next().unwrap(), 'a');
2623 /// assert_eq!(into_iter.next().unwrap(), 'b');
2624 /// assert_eq!(into_iter.next().unwrap(), 'z');
2625 /// ```
2626 pub fn as_mut_slice(&mut self) -> &mut [T] {
2627 unsafe { &mut *self.as_raw_mut_slice() }
2628 }
2629
2630 fn as_raw_mut_slice(&mut self) -> *mut [T] {
2631 unsafe { ptr::slice_from_raw_parts_mut(self.vec.data_raw().add(self.start), self.len()) }
2632 }
2633}
2634
2635impl<T> Iterator for IntoIter<T> {
2636 type Item = T;
2637 fn next(&mut self) -> Option<T> {
2638 if self.start == self.vec.len() {
2639 None
2640 } else {
2641 unsafe {
2642 let old_start = self.start;
2643 self.start += 1;
2644 Some(ptr::read(self.vec.data_raw().add(old_start)))
2645 }
2646 }
2647 }
2648
2649 fn size_hint(&self) -> (usize, Option<usize>) {
2650 let len = self.vec.len() - self.start;
2651 (len, Some(len))
2652 }
2653}
2654
2655impl<T> DoubleEndedIterator for IntoIter<T> {
2656 fn next_back(&mut self) -> Option<T> {
2657 if self.start == self.vec.len() {
2658 None
2659 } else {
2660 self.vec.pop()
2661 }
2662 }
2663}
2664
2665impl<T> ExactSizeIterator for IntoIter<T> {}
2666
2667impl<T> core::iter::FusedIterator for IntoIter<T> {}
2668
2669// SAFETY: the length calculation is trivial, we're an array! And if it's wrong we're So Screwed.
2670#[cfg(feature = "unstable")]
2671unsafe impl<T> core::iter::TrustedLen for IntoIter<T> {}
2672
2673impl<T> Drop for IntoIter<T> {
2674 #[inline]
2675 fn drop(&mut self) {
2676 #[cold]
2677 #[inline(never)]
2678 fn drop_non_singleton<T>(this: &mut IntoIter<T>) {
2679 // Leak on panic.
2680 struct DropGuard<'a, T>(&'a mut IntoIter<T>);
2681 impl<T> Drop for DropGuard<'_, T> {
2682 fn drop(&mut self) {
2683 unsafe {
2684 self.0.vec.set_len_non_singleton(0);
2685 }
2686 }
2687 }
2688 unsafe {
2689 let guard = DropGuard(this);
2690 ptr::drop_in_place(&mut guard.0.vec[guard.0.start..]);
2691 }
2692 }
2693
2694 if !self.vec.is_singleton() {
2695 drop_non_singleton(self);
2696 }
2697 }
2698}
2699
2700impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
2701 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2702 f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
2703 }
2704}
2705
2706impl<T> AsRef<[T]> for IntoIter<T> {
2707 fn as_ref(&self) -> &[T] {
2708 self.as_slice()
2709 }
2710}
2711
2712impl<T: Clone> Clone for IntoIter<T> {
2713 #[allow(clippy::into_iter_on_ref)]
2714 fn clone(&self) -> Self {
2715 // Just create a new `ThinVec` from the remaining elements and IntoIter it
2716 self.as_slice()
2717 .into_iter()
2718 .cloned()
2719 .collect::<ThinVec<_>>()
2720 .into_iter()
2721 }
2722}
2723
2724/// A draining iterator for `ThinVec<T>`.
2725///
2726/// This `struct` is created by [`ThinVec::drain`].
2727/// See its documentation for more.
2728///
2729/// # Example
2730///
2731/// ```
2732/// use thin_vec::thin_vec;
2733///
2734/// let mut v = thin_vec![0, 1, 2];
2735/// let iter: thin_vec::Drain<_> = v.drain(..);
2736/// ```
2737pub struct Drain<'a, T> {
2738 // Ok so ThinVec::drain takes a range of the ThinVec and yields the contents by-value,
2739 // then backshifts the array. During iteration the array is in an unsound state
2740 // (big deinitialized hole in it), and this is very dangerous.
2741 //
2742 // Our first line of defense is the borrow checker: we have a mutable borrow, so nothing
2743 // can access the ThinVec while we exist. As long as we make sure the ThinVec is in a valid
2744 // state again before we release the borrow, everything should be A-OK! We do this cleanup
2745 // in our Drop impl.
2746 //
2747 // Unfortunately, that's unsound, because mem::forget exists and The Leakpocalypse Is Real.
2748 // So we can't actually guarantee our destructor runs before our borrow expires. Thankfully
2749 // this isn't fatal: we can just set the ThinVec's len to 0 at the start, so if anyone
2750 // leaks the Drain, we just leak everything the ThinVec contained out of spite! If they
2751 // *don't* leak us then we can properly repair the len in our Drop impl. This is known
2752 // as "leak amplification", and is the same approach std uses.
2753 //
2754 // But we can do slightly better than setting the len to 0! The drain breaks us up into
2755 // these parts:
2756 //
2757 // ```text
2758 //
2759 // [A, B, C, D, E, F, G, H, _, _]
2760 // ____ __________ ____ ____
2761 // | | | |
2762 // prefix drain tail spare-cap
2763 // ```
2764 //
2765 // As the drain iterator is consumed from both ends (DoubleEnded!), we'll start to look
2766 // like this:
2767 //
2768 // ```text
2769 // [A, B, _, _, E, _, G, H, _, _]
2770 // ____ __________ ____ ____
2771 // | | | |
2772 // prefix drain tail spare-cap
2773 // ```
2774 //
2775 // Note that the prefix is always valid and untouched, as such we can set the len
2776 // to the prefix when doing leak-amplification. As a bonus, we can use this value
2777 // to remember where the drain range starts. At the end we'll look like this
2778 // (we exhaust ourselves in our Drop impl):
2779 //
2780 // ```text
2781 // [A, B, _, _, _, _, G, H, _, _]
2782 // _____ __________ _____ ____
2783 // | | | |
2784 // len drain tail spare-cap
2785 // ```
2786 //
2787 // And need to become this:
2788 //
2789 // ```text
2790 // [A, B, G, H, _, _, _, _, _, _]
2791 // ___________ ________________
2792 // | |
2793 // len spare-cap
2794 // ```
2795 //
2796 // All this requires is moving the tail back to the prefix (stored in `len`)
2797 // and setting `len` to `len + tail_len` to undo the leak amplification.
2798 /// An iterator over the elements we're removing.
2799 ///
2800 /// As we go we'll be `read`ing out of the shared refs yielded by this.
2801 /// It's ok to use Iter here because it promises to only take refs to the parts
2802 /// we haven't yielded yet.
2803 iter: Iter<'a, T>,
2804 /// The actual ThinVec, which we need to hold onto to undo the leak amplification
2805 /// and backshift the tail into place. This should only be accessed when we're
2806 /// completely done with the Iter in the `drop` impl of this type (or miri will get mad).
2807 ///
2808 /// Since we set the `len` of this to be before `Iter`, we can use that `len`
2809 /// to retrieve the index of the start of the drain range later.
2810 vec: NonNull<ThinVec<T>>,
2811 /// The one-past-the-end index of the drain range, or equivalently the start of the tail.
2812 end: usize,
2813 /// The length of the tail.
2814 tail: usize,
2815}
2816
2817impl<'a, T> Iterator for Drain<'a, T> {
2818 type Item = T;
2819 fn next(&mut self) -> Option<T> {
2820 self.iter.next().map(|x| unsafe { ptr::read(x) })
2821 }
2822
2823 fn size_hint(&self) -> (usize, Option<usize>) {
2824 self.iter.size_hint()
2825 }
2826}
2827
2828impl<'a, T> DoubleEndedIterator for Drain<'a, T> {
2829 fn next_back(&mut self) -> Option<T> {
2830 self.iter.next_back().map(|x| unsafe { ptr::read(x) })
2831 }
2832}
2833
2834impl<'a, T> ExactSizeIterator for Drain<'a, T> {}
2835
2836// SAFETY: we need to keep track of this perfectly Or Else anyway!
2837#[cfg(feature = "unstable")]
2838unsafe impl<T> core::iter::TrustedLen for Drain<'_, T> {}
2839
2840impl<T> core::iter::FusedIterator for Drain<'_, T> {}
2841
2842impl<'a, T> Drop for Drain<'a, T> {
2843 fn drop(&mut self) {
2844 // Consume the rest of the iterator.
2845 for _ in self.by_ref() {}
2846
2847 // Move the tail over the drained items, and update the length.
2848 unsafe {
2849 let vec = self.vec.as_mut();
2850
2851 // Don't mutate the empty singleton!
2852 if !vec.is_singleton() {
2853 let old_len = vec.len();
2854 let start = vec.data_raw().add(old_len);
2855 let end = vec.data_raw().add(self.end);
2856 ptr::copy(end, start, self.tail);
2857 vec.set_len_non_singleton(old_len + self.tail);
2858 }
2859 }
2860 }
2861}
2862
2863impl<T: fmt::Debug> fmt::Debug for Drain<'_, T> {
2864 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2865 f.debug_tuple("Drain").field(&self.iter.as_slice()).finish()
2866 }
2867}
2868
2869impl<'a, T> Drain<'a, T> {
2870 /// Returns the remaining items of this iterator as a slice.
2871 ///
2872 /// # Examples
2873 ///
2874 /// ```
2875 /// use thin_vec::thin_vec;
2876 ///
2877 /// let mut vec = thin_vec!['a', 'b', 'c'];
2878 /// let mut drain = vec.drain(..);
2879 /// assert_eq!(drain.as_slice(), &['a', 'b', 'c']);
2880 /// let _ = drain.next().unwrap();
2881 /// assert_eq!(drain.as_slice(), &['b', 'c']);
2882 /// ```
2883 #[must_use]
2884 pub fn as_slice(&self) -> &[T] {
2885 // SAFETY: this is A-OK because the elements that the underlying
2886 // iterator still points at are still logically initialized and contiguous.
2887 self.iter.as_slice()
2888 }
2889}
2890
2891impl<'a, T> AsRef<[T]> for Drain<'a, T> {
2892 fn as_ref(&self) -> &[T] {
2893 self.as_slice()
2894 }
2895}
2896
2897/// A splicing iterator for `ThinVec`.
2898///
2899/// This struct is created by [`ThinVec::splice`][].
2900/// See its documentation for more.
2901///
2902/// # Example
2903///
2904/// ```
2905/// use thin_vec::thin_vec;
2906///
2907/// let mut v = thin_vec![0, 1, 2];
2908/// let new = [7, 8];
2909/// let iter: thin_vec::Splice<_> = v.splice(1.., new);
2910/// ```
2911#[derive(Debug)]
2912pub struct Splice<'a, I: Iterator + 'a> {
2913 drain: Drain<'a, I::Item>,
2914 replace_with: I,
2915}
2916
2917impl<I: Iterator> Iterator for Splice<'_, I> {
2918 type Item = I::Item;
2919
2920 fn next(&mut self) -> Option<Self::Item> {
2921 self.drain.next()
2922 }
2923
2924 fn size_hint(&self) -> (usize, Option<usize>) {
2925 self.drain.size_hint()
2926 }
2927}
2928
2929impl<I: Iterator> DoubleEndedIterator for Splice<'_, I> {
2930 fn next_back(&mut self) -> Option<Self::Item> {
2931 self.drain.next_back()
2932 }
2933}
2934
2935impl<I: Iterator> ExactSizeIterator for Splice<'_, I> {}
2936
2937impl<I: Iterator> Drop for Splice<'_, I> {
2938 fn drop(&mut self) {
2939 // Ensure we've fully drained out the range
2940 self.drain.by_ref().for_each(drop);
2941
2942 unsafe {
2943 // If there's no tail elements, then the inner ThinVec is already
2944 // correct and we can just extend it like normal.
2945 if self.drain.tail == 0 {
2946 self.drain.vec.as_mut().extend(self.replace_with.by_ref());
2947 return;
2948 }
2949
2950 // First fill the range left by drain().
2951 if !self.drain.fill(&mut self.replace_with) {
2952 return;
2953 }
2954
2955 // There may be more elements. Use the lower bound as an estimate.
2956 let (lower_bound, _upper_bound) = self.replace_with.size_hint();
2957 if lower_bound > 0 {
2958 self.drain.move_tail(lower_bound);
2959 if !self.drain.fill(&mut self.replace_with) {
2960 return;
2961 }
2962 }
2963
2964 // Collect any remaining elements.
2965 // This is a zero-length vector which does not allocate if `lower_bound` was exact.
2966 let mut collected = self
2967 .replace_with
2968 .by_ref()
2969 .collect::<Vec<I::Item>>()
2970 .into_iter();
2971 // Now we have an exact count.
2972 if collected.len() > 0 {
2973 self.drain.move_tail(collected.len());
2974 let filled = self.drain.fill(&mut collected);
2975 debug_assert!(filled);
2976 debug_assert_eq!(collected.len(), 0);
2977 }
2978 }
2979 // Let `Drain::drop` move the tail back if necessary and restore `vec.len`.
2980 }
2981}
2982
2983#[cfg(feature = "gecko-ffi")]
2984#[repr(C, align(8))]
2985struct AutoBuffer<T, const N: usize> {
2986 header: Header,
2987 buffer: mem::MaybeUninit<[T; N]>,
2988}
2989
2990#[doc(hidden)]
2991#[cfg(feature = "gecko-ffi")]
2992#[repr(C)]
2993pub struct AutoThinVec<T, const N: usize> {
2994 inner: ThinVec<T>,
2995 buffer: AutoBuffer<T, N>,
2996 _pinned: core::marker::PhantomPinned,
2997}
2998
2999#[cfg(feature = "gecko-ffi")]
3000impl<T, const N: usize> AutoThinVec<T, N> {
3001 /// Implementation detail for the auto_thin_vec macro.
3002 #[inline]
3003 #[doc(hidden)]
3004 pub fn new_unpinned() -> Self {
3005 // This condition is hard-coded in nsTArray.h
3006 assert!(
3007 core::mem::align_of::<T>() <= 8,
3008 "Can't handle alignments greater than 8"
3009 );
3010 assert_eq!(
3011 core::mem::offset_of!(Self, buffer),
3012 AUTO_ARRAY_HEADER_OFFSET
3013 );
3014 Self {
3015 inner: ThinVec::new(),
3016 buffer: AutoBuffer {
3017 header: Header {
3018 _len: 0,
3019 _cap: pack_capacity_and_auto(N as SizeType, true),
3020 },
3021 buffer: mem::MaybeUninit::uninit(),
3022 },
3023 _pinned: core::marker::PhantomPinned,
3024 }
3025 }
3026
3027 /// Returns a raw pointer to the inner ThinVec. Note that if you dereference it from rust, you
3028 /// need to make sure not to move the ThinVec manually via something like
3029 /// `std::mem::take(&mut auto_vec)`.
3030 pub fn as_mut_ptr(self: core::pin::Pin<&mut Self>) -> *mut ThinVec<T> {
3031 debug_assert!(self.is_auto_array());
3032 unsafe { &mut self.get_unchecked_mut().inner }
3033 }
3034
3035 #[inline]
3036 pub unsafe fn shrink_to_fit_known_singleton(self: core::pin::Pin<&mut Self>) {
3037 debug_assert!(self.is_singleton());
3038 let this = unsafe { self.get_unchecked_mut() };
3039 this.buffer.header.set_len(0);
3040 // TODO(emilio): Use NonNull::from_mut when msrv allows.
3041 this.inner.ptr = unsafe { NonNull::new_unchecked(&mut this.buffer.header) };
3042 debug_assert!(this.inner.is_auto_array());
3043 debug_assert!(this.inner.uses_stack_allocated_buffer());
3044 }
3045
3046 pub fn shrink_to_fit(self: core::pin::Pin<&mut Self>) {
3047 let this = unsafe { self.get_unchecked_mut() };
3048 this.inner.shrink_to_fit();
3049 debug_assert!(this.inner.is_auto_array());
3050 }
3051}
3052
3053// NOTE(emilio): DerefMut wouldn't be safe, see the comment in as_mut_ptr.
3054#[cfg(feature = "gecko-ffi")]
3055impl<T, const N: usize> Deref for AutoThinVec<T, N> {
3056 type Target = ThinVec<T>;
3057
3058 fn deref(&self) -> &Self::Target {
3059 &self.inner
3060 }
3061}
3062
3063/// Create a ThinVec<$ty> named `$name`, with capacity for `$cap` inline elements.
3064///
3065/// TODO(emilio): This would be a lot more convenient to use with super let, see
3066/// <https://github.com/rust-lang/rust/issues/139076>
3067#[cfg(feature = "gecko-ffi")]
3068#[macro_export]
3069macro_rules! auto_thin_vec {
3070 (let $name:ident : [$ty:ty; $cap:literal]) => {
3071 let auto_vec = $crate::AutoThinVec::<$ty, $cap>::new_unpinned();
3072 let mut $name = core::pin::pin!(auto_vec);
3073 unsafe { $name.as_mut().shrink_to_fit_known_singleton() };
3074 };
3075}
3076
3077/// Private helper methods for `Splice::drop`
3078impl<T> Drain<'_, T> {
3079 /// The range from `self.vec.len` to `self.tail_start` contains elements
3080 /// that have been moved out.
3081 /// Fill that range as much as possible with new elements from the `replace_with` iterator.
3082 /// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.)
3083 unsafe fn fill<I: Iterator<Item = T>>(&mut self, replace_with: &mut I) -> bool {
3084 let vec = unsafe { self.vec.as_mut() };
3085 let range_start = vec.len();
3086 let range_end = self.end;
3087 let range_slice = unsafe {
3088 slice::from_raw_parts_mut(vec.data_raw().add(range_start), range_end - range_start)
3089 };
3090
3091 for place in range_slice {
3092 let Some(new_item) = replace_with.next() else {
3093 return false;
3094 };
3095 unsafe {
3096 ptr::write(place, new_item);
3097 vec.set_len(vec.len() + 1);
3098 }
3099 }
3100 true
3101 }
3102
3103 /// Makes room for inserting more elements before the tail.
3104 unsafe fn move_tail(&mut self, additional: usize) {
3105 let vec = unsafe { self.vec.as_mut() };
3106 let len = self.end + self.tail;
3107 vec.reserve(len.checked_add(additional).unwrap_cap_overflow());
3108
3109 let new_tail_start = self.end + additional;
3110 unsafe {
3111 let src = vec.data_raw().add(self.end);
3112 let dst = vec.data_raw().add(new_tail_start);
3113 ptr::copy(src, dst, self.tail);
3114 }
3115 self.end = new_tail_start;
3116 }
3117}
3118
3119/// An iterator for [`ThinVec`] which uses a closure to determine if an element should be removed.
3120#[must_use = "iterators are lazy and do nothing unless consumed"]
3121pub struct ExtractIf<'a, T, F> {
3122 vec: &'a mut ThinVec<T>,
3123 /// The index of the item that will be inspected by the next call to `next`.
3124 idx: usize,
3125 /// Elements at and beyond this point will be retained. Must be equal or smaller than `old_len`.
3126 end: usize,
3127 /// The number of items that have been drained (removed) thus far.
3128 del: usize,
3129 /// The original length of `vec` prior to draining.
3130 old_len: usize,
3131 /// The filter test predicate.
3132 pred: F,
3133}
3134
3135impl<T, F> Iterator for ExtractIf<'_, T, F>
3136where
3137 F: FnMut(&mut T) -> bool,
3138{
3139 type Item = T;
3140
3141 fn next(&mut self) -> Option<T> {
3142 unsafe {
3143 let v = self.vec.data_raw();
3144 while self.idx < self.end {
3145 let i = self.idx;
3146 let drained = (self.pred)(&mut *v.add(i));
3147 // Update the index *after* the predicate is called. If the index
3148 // is updated prior and the predicate panics, the element at this
3149 // index would be leaked.
3150 self.idx += 1;
3151 if drained {
3152 self.del += 1;
3153 return Some(ptr::read(v.add(i)));
3154 } else if self.del > 0 {
3155 let del = self.del;
3156 let src: *const T = v.add(i);
3157 let dst: *mut T = v.add(i - del);
3158 ptr::copy_nonoverlapping(src, dst, 1);
3159 }
3160 }
3161 None
3162 }
3163 }
3164
3165 fn size_hint(&self) -> (usize, Option<usize>) {
3166 (0, Some(self.end - self.idx))
3167 }
3168}
3169
3170impl<A, F> Drop for ExtractIf<'_, A, F> {
3171 fn drop(&mut self) {
3172 unsafe {
3173 if self.idx < self.old_len && self.del > 0 {
3174 // This is a pretty messed up state, and there isn't really an
3175 // obviously right thing to do. We don't want to keep trying
3176 // to execute `pred`, so we just backshift all the unprocessed
3177 // elements and tell the vec that they still exist. The backshift
3178 // is required to prevent a double-drop of the last successfully
3179 // drained item prior to a panic in the predicate.
3180 let ptr = self.vec.data_raw();
3181 let src = ptr.add(self.idx);
3182 let dst = src.sub(self.del);
3183 let tail_len = self.old_len - self.idx;
3184 src.copy_to(dst, tail_len);
3185 }
3186
3187 self.vec.set_len(self.old_len - self.del);
3188 }
3189 }
3190}
3191
3192/// Write is implemented for `ThinVec<u8>` by appending to the vector.
3193/// The vector will grow as needed.
3194/// This implementation is identical to the one for `Vec<u8>`.
3195#[cfg(feature = "std")]
3196impl std::io::Write for ThinVec<u8> {
3197 #[inline]
3198 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
3199 self.extend_from_slice(buf);
3200 Ok(buf.len())
3201 }
3202
3203 #[inline]
3204 fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
3205 self.extend_from_slice(buf);
3206 Ok(())
3207 }
3208
3209 #[inline]
3210 fn flush(&mut self) -> std::io::Result<()> {
3211 Ok(())
3212 }
3213}
3214
3215// TODO: a million Index impls
3216
3217#[cfg(test)]
3218mod tests {
3219 use super::{MAX_CAP, ThinVec};
3220 use crate::alloc::{string::ToString, vec};
3221
3222 #[test]
3223 fn test_size_of() {
3224 use core::mem::size_of;
3225 assert_eq!(size_of::<ThinVec<u8>>(), size_of::<&u8>());
3226
3227 assert_eq!(size_of::<Option<ThinVec<u8>>>(), size_of::<&u8>());
3228 }
3229
3230 #[test]
3231 fn test_drop_empty() {
3232 ThinVec::<u8>::new();
3233 }
3234
3235 #[test]
3236 #[should_panic]
3237 fn test_cap_plus_header_rounded_up_overflows() {
3238 let _ = ThinVec::<u8>::with_capacity(isize::MAX as usize - size_of::<super::Header>());
3239 }
3240
3241 #[test]
3242 fn test_data_ptr_alignment() {
3243 let v = ThinVec::<u16>::new();
3244 assert!(v.data_raw() as usize % core::mem::align_of::<u16>() == 0);
3245
3246 let v = ThinVec::<u32>::new();
3247 assert!(v.data_raw() as usize % core::mem::align_of::<u32>() == 0);
3248
3249 let v = ThinVec::<u64>::new();
3250 assert!(v.data_raw() as usize % core::mem::align_of::<u64>() == 0);
3251 }
3252
3253 #[test]
3254 #[cfg_attr(
3255 feature = "gecko-ffi",
3256 should_panic = "nsTArray does not handle alignment above the header size correctly"
3257 )]
3258 fn test_overaligned_type_is_rejected_for_gecko_ffi_mode() {
3259 #[repr(align(16))]
3260 #[allow(unused)]
3261 struct Align16(u8);
3262
3263 let v = ThinVec::<Align16>::new();
3264 assert!(v.data_raw() as usize % 16 == 0);
3265 }
3266
3267 #[test]
3268 fn test_partial_eq() {
3269 assert_eq!(thin_vec![0], thin_vec![0]);
3270 assert_ne!(thin_vec![0], thin_vec![1]);
3271 assert_eq!(thin_vec![1, 2, 3], vec![1, 2, 3]);
3272 }
3273
3274 #[test]
3275 fn test_alloc() {
3276 let mut v = ThinVec::new();
3277 assert!(!v.has_allocation());
3278 v.push(1);
3279 assert!(v.has_allocation());
3280 v.pop();
3281 assert!(v.has_allocation());
3282 v.shrink_to_fit();
3283 assert!(!v.has_allocation());
3284 v.reserve(64);
3285 assert!(v.has_allocation());
3286 v = ThinVec::with_capacity(64);
3287 assert!(v.has_allocation());
3288 v = ThinVec::with_capacity(0);
3289 assert!(!v.has_allocation());
3290 }
3291
3292 #[test]
3293 fn test_drain_items() {
3294 let mut vec = thin_vec![1, 2, 3];
3295 let mut vec2 = thin_vec![];
3296 for i in vec.drain(..) {
3297 vec2.push(i);
3298 }
3299 assert_eq!(vec, []);
3300 assert_eq!(vec2, [1, 2, 3]);
3301 }
3302
3303 #[test]
3304 fn test_drain_items_reverse() {
3305 let mut vec = thin_vec![1, 2, 3];
3306 let mut vec2 = thin_vec![];
3307 for i in vec.drain(..).rev() {
3308 vec2.push(i);
3309 }
3310 assert_eq!(vec, []);
3311 assert_eq!(vec2, [3, 2, 1]);
3312 }
3313
3314 #[test]
3315 #[cfg_attr(
3316 feature = "gecko-ffi",
3317 should_panic = "ThinVec<T> cannot bridge to nsTArray<T> when T is zero-sized"
3318 )]
3319 fn test_drain_items_zero_sized() {
3320 let mut vec = thin_vec![(), (), ()];
3321 let mut vec2 = thin_vec![];
3322 for i in vec.drain(..) {
3323 vec2.push(i);
3324 }
3325 assert_eq!(vec, []);
3326 assert_eq!(vec2, [(), (), ()]);
3327 }
3328
3329 #[test]
3330 #[should_panic]
3331 fn test_drain_out_of_bounds() {
3332 let mut v = thin_vec![1, 2, 3, 4, 5];
3333 v.drain(5..6);
3334 }
3335
3336 #[test]
3337 fn test_drain_range() {
3338 let mut v = thin_vec![1, 2, 3, 4, 5];
3339 for _ in v.drain(4..) {}
3340 assert_eq!(v, &[1, 2, 3, 4]);
3341
3342 let mut v: ThinVec<_> = (1..6).map(|x| x.to_string()).collect();
3343 for _ in v.drain(1..4) {}
3344 assert_eq!(v, &[1.to_string(), 5.to_string()]);
3345
3346 let mut v: ThinVec<_> = (1..6).map(|x| x.to_string()).collect();
3347 for _ in v.drain(1..4).rev() {}
3348 assert_eq!(v, &[1.to_string(), 5.to_string()]);
3349 }
3350
3351 #[test]
3352 #[cfg_attr(
3353 feature = "gecko-ffi",
3354 should_panic = "ThinVec<T> cannot bridge to nsTArray<T> when T is zero-sized"
3355 )]
3356 fn test_drain_range_zst() {
3357 let mut v: ThinVec<_> = thin_vec![(); 5];
3358 for _ in v.drain(1..4).rev() {}
3359 assert_eq!(v, &[(), ()]);
3360 }
3361
3362 #[test]
3363 #[cfg_attr(
3364 feature = "gecko-ffi",
3365 should_panic = "ThinVec<T> cannot bridge to nsTArray<T> when T is zero-sized"
3366 )]
3367 fn test_drain_max_vec_size() {
3368 let mut v = ThinVec::<()>::with_capacity(MAX_CAP);
3369 unsafe {
3370 v.set_len(MAX_CAP);
3371 }
3372 for _ in v.drain(MAX_CAP - 1..) {}
3373 assert_eq!(v.len(), MAX_CAP - 1);
3374 }
3375
3376 #[test]
3377 fn test_clear() {
3378 let mut v = ThinVec::<i32>::new();
3379 assert_eq!(v.len(), 0);
3380 assert_eq!(v.capacity(), 0);
3381 assert_eq!(&v[..], &[]);
3382
3383 v.clear();
3384 assert_eq!(v.len(), 0);
3385 assert_eq!(v.capacity(), 0);
3386 assert_eq!(&v[..], &[]);
3387
3388 v.push(1);
3389 v.push(2);
3390 assert_eq!(v.len(), 2);
3391 assert!(v.capacity() >= 2);
3392 assert_eq!(&v[..], &[1, 2]);
3393
3394 v.clear();
3395 assert_eq!(v.len(), 0);
3396 assert!(v.capacity() >= 2);
3397 assert_eq!(&v[..], &[]);
3398
3399 v.push(3);
3400 v.push(4);
3401 assert_eq!(v.len(), 2);
3402 assert!(v.capacity() >= 2);
3403 assert_eq!(&v[..], &[3, 4]);
3404
3405 v.clear();
3406 assert_eq!(v.len(), 0);
3407 assert!(v.capacity() >= 2);
3408 assert_eq!(&v[..], &[]);
3409
3410 v.clear();
3411 assert_eq!(v.len(), 0);
3412 assert!(v.capacity() >= 2);
3413 assert_eq!(&v[..], &[]);
3414 }
3415
3416 #[test]
3417 fn test_empty_singleton_torture() {
3418 {
3419 let mut v = ThinVec::<i32>::new();
3420 assert_eq!(v.len(), 0);
3421 assert_eq!(v.capacity(), 0);
3422 assert!(v.is_empty());
3423 assert_eq!(&v[..], &[]);
3424 assert_eq!(&mut v[..], &mut []);
3425
3426 assert_eq!(v.pop(), None);
3427 assert_eq!(v.len(), 0);
3428 assert_eq!(v.capacity(), 0);
3429 assert_eq!(&v[..], &[]);
3430 }
3431
3432 {
3433 let v = ThinVec::<i32>::new();
3434 assert_eq!(v.into_iter().count(), 0);
3435
3436 let v = ThinVec::<i32>::new();
3437 #[allow(clippy::never_loop)]
3438 for _ in v.into_iter() {
3439 unreachable!();
3440 }
3441 }
3442
3443 {
3444 let mut v = ThinVec::<i32>::new();
3445 assert_eq!(v.drain(..).len(), 0);
3446
3447 #[allow(clippy::never_loop)]
3448 for _ in v.drain(..) {
3449 unreachable!()
3450 }
3451
3452 assert_eq!(v.len(), 0);
3453 assert_eq!(v.capacity(), 0);
3454 assert_eq!(&v[..], &[]);
3455 }
3456
3457 {
3458 let mut v = ThinVec::<i32>::new();
3459 assert_eq!(v.splice(.., []).len(), 0);
3460
3461 #[allow(clippy::never_loop)]
3462 for _ in v.splice(.., []) {
3463 unreachable!()
3464 }
3465
3466 assert_eq!(v.len(), 0);
3467 assert_eq!(v.capacity(), 0);
3468 assert_eq!(&v[..], &[]);
3469 }
3470
3471 {
3472 let mut v = ThinVec::<i32>::new();
3473 v.truncate(1);
3474 assert_eq!(v.len(), 0);
3475 assert_eq!(v.capacity(), 0);
3476 assert_eq!(&v[..], &[]);
3477
3478 v.truncate(0);
3479 assert_eq!(v.len(), 0);
3480 assert_eq!(v.capacity(), 0);
3481 assert_eq!(&v[..], &[]);
3482 }
3483
3484 {
3485 let mut v = ThinVec::<i32>::new();
3486 v.shrink_to_fit();
3487 assert_eq!(v.len(), 0);
3488 assert_eq!(v.capacity(), 0);
3489 assert_eq!(&v[..], &[]);
3490 }
3491
3492 {
3493 let mut v = ThinVec::<i32>::new();
3494 let new = v.split_off(0);
3495 assert_eq!(v.len(), 0);
3496 assert_eq!(v.capacity(), 0);
3497 assert_eq!(&v[..], &[]);
3498
3499 assert_eq!(new.len(), 0);
3500 assert_eq!(new.capacity(), 0);
3501 assert_eq!(&new[..], &[]);
3502 }
3503
3504 {
3505 let mut v = ThinVec::<i32>::new();
3506 let mut other = ThinVec::<i32>::new();
3507 v.append(&mut other);
3508
3509 assert_eq!(v.len(), 0);
3510 assert_eq!(v.capacity(), 0);
3511 assert_eq!(&v[..], &[]);
3512
3513 assert_eq!(other.len(), 0);
3514 assert_eq!(other.capacity(), 0);
3515 assert_eq!(&other[..], &[]);
3516 }
3517
3518 {
3519 let mut v = ThinVec::<i32>::new();
3520 v.reserve(0);
3521
3522 assert_eq!(v.len(), 0);
3523 assert_eq!(v.capacity(), 0);
3524 assert_eq!(&v[..], &[]);
3525 }
3526
3527 {
3528 let mut v = ThinVec::<i32>::new();
3529 v.reserve_exact(0);
3530
3531 assert_eq!(v.len(), 0);
3532 assert_eq!(v.capacity(), 0);
3533 assert_eq!(&v[..], &[]);
3534 }
3535
3536 {
3537 let mut v = ThinVec::<i32>::new();
3538 v.reserve(0);
3539
3540 assert_eq!(v.len(), 0);
3541 assert_eq!(v.capacity(), 0);
3542 assert_eq!(&v[..], &[]);
3543 }
3544
3545 {
3546 let v = ThinVec::<i32>::with_capacity(0);
3547
3548 assert_eq!(v.len(), 0);
3549 assert_eq!(v.capacity(), 0);
3550 assert_eq!(&v[..], &[]);
3551 }
3552
3553 {
3554 let v = ThinVec::<i32>::default();
3555
3556 assert_eq!(v.len(), 0);
3557 assert_eq!(v.capacity(), 0);
3558 assert_eq!(&v[..], &[]);
3559 }
3560
3561 {
3562 let mut v = ThinVec::<i32>::new();
3563 v.retain(|_| unreachable!());
3564
3565 assert_eq!(v.len(), 0);
3566 assert_eq!(v.capacity(), 0);
3567 assert_eq!(&v[..], &[]);
3568 }
3569
3570 {
3571 let mut v = ThinVec::<i32>::new();
3572 v.retain_mut(|_| unreachable!());
3573
3574 assert_eq!(v.len(), 0);
3575 assert_eq!(v.capacity(), 0);
3576 assert_eq!(&v[..], &[]);
3577 }
3578
3579 {
3580 let mut v = ThinVec::<i32>::new();
3581 v.dedup_by_key(|x| *x);
3582
3583 assert_eq!(v.len(), 0);
3584 assert_eq!(v.capacity(), 0);
3585 assert_eq!(&v[..], &[]);
3586 }
3587
3588 {
3589 let mut v = ThinVec::<i32>::new();
3590 v.dedup_by(|_, _| unreachable!());
3591
3592 assert_eq!(v.len(), 0);
3593 assert_eq!(v.capacity(), 0);
3594 assert_eq!(&v[..], &[]);
3595 }
3596
3597 {
3598 let v = ThinVec::<i32>::new();
3599 let v = v.clone();
3600
3601 assert_eq!(v.len(), 0);
3602 assert_eq!(v.capacity(), 0);
3603 assert_eq!(&v[..], &[]);
3604 }
3605 }
3606
3607 #[test]
3608 fn test_clone() {
3609 let mut v = ThinVec::<i32>::new();
3610 assert!(v.is_singleton());
3611 v.push(0);
3612 v.pop();
3613 assert!(!v.is_singleton());
3614
3615 let v2 = v.clone();
3616 assert!(v2.is_singleton());
3617 }
3618}
3619
3620#[cfg(test)]
3621mod std_tests {
3622 #![allow(clippy::reversed_empty_ranges)]
3623
3624 use super::*;
3625 use crate::alloc::{
3626 format,
3627 string::{String, ToString},
3628 };
3629 use core::mem::size_of;
3630
3631 struct DropCounter<'a> {
3632 count: &'a mut u32,
3633 }
3634
3635 impl<'a> Drop for DropCounter<'a> {
3636 fn drop(&mut self) {
3637 *self.count += 1;
3638 }
3639 }
3640
3641 #[test]
3642 fn test_small_vec_struct() {
3643 assert!(size_of::<ThinVec<u8>>() == size_of::<usize>());
3644 }
3645
3646 #[test]
3647 fn test_double_drop() {
3648 struct TwoVec<T> {
3649 x: ThinVec<T>,
3650 y: ThinVec<T>,
3651 }
3652
3653 let (mut count_x, mut count_y) = (0, 0);
3654 {
3655 let mut tv = TwoVec {
3656 x: ThinVec::new(),
3657 y: ThinVec::new(),
3658 };
3659 tv.x.push(DropCounter {
3660 count: &mut count_x,
3661 });
3662 tv.y.push(DropCounter {
3663 count: &mut count_y,
3664 });
3665
3666 // If ThinVec had a drop flag, here is where it would be zeroed.
3667 // Instead, it should rely on its internal state to prevent
3668 // doing anything significant when dropped multiple times.
3669 drop(tv.x);
3670
3671 // Here tv goes out of scope, tv.y should be dropped, but not tv.x.
3672 }
3673
3674 assert_eq!(count_x, 1);
3675 assert_eq!(count_y, 1);
3676 }
3677
3678 #[test]
3679 fn test_reserve() {
3680 let mut v = ThinVec::new();
3681 assert_eq!(v.capacity(), 0);
3682
3683 v.reserve(2);
3684 assert!(v.capacity() >= 2);
3685
3686 for i in 0..16 {
3687 v.push(i);
3688 }
3689
3690 assert!(v.capacity() >= 16);
3691 v.reserve(16);
3692 assert!(v.capacity() >= 32);
3693
3694 v.push(16);
3695
3696 v.reserve(16);
3697 assert!(v.capacity() >= 33)
3698 }
3699
3700 #[test]
3701 fn test_extend() {
3702 let mut v = ThinVec::<usize>::new();
3703 let mut w = ThinVec::new();
3704 v.extend(w.clone());
3705 assert_eq!(v, &[]);
3706
3707 v.extend(0..3);
3708 for i in 0..3 {
3709 w.push(i)
3710 }
3711
3712 assert_eq!(v, w);
3713
3714 v.extend(3..10);
3715 for i in 3..10 {
3716 w.push(i)
3717 }
3718
3719 assert_eq!(v, w);
3720
3721 v.extend(w.clone()); // specializes to `append`
3722 assert!(v.iter().eq(w.iter().chain(w.iter())));
3723
3724 // Double drop
3725 let mut count_x = 0;
3726 {
3727 let mut x = ThinVec::new();
3728 let y = thin_vec![DropCounter {
3729 count: &mut count_x
3730 }];
3731 x.extend(y);
3732 }
3733
3734 assert_eq!(count_x, 1);
3735 }
3736
3737 #[test]
3738 #[cfg_attr(
3739 feature = "gecko-ffi",
3740 should_panic = "ThinVec<T> cannot bridge to nsTArray<T> when T is zero-sized"
3741 )]
3742 fn test_extend_zst() {
3743 #[derive(PartialEq, Debug)]
3744 struct Foo;
3745
3746 let mut a = ThinVec::new();
3747 let b = thin_vec![Foo, Foo];
3748
3749 a.extend(b);
3750 assert_eq!(a, &[Foo, Foo]);
3751 }
3752
3753 /* TODO: implement extend for Iter<&Copy>
3754 #[test]
3755 fn test_extend_ref() {
3756 let mut v = thin_vec![1, 2];
3757 v.extend(&[3, 4, 5]);
3758
3759 assert_eq!(v.len(), 5);
3760 assert_eq!(v, [1, 2, 3, 4, 5]);
3761
3762 let w = thin_vec![6, 7];
3763 v.extend(&w);
3764
3765 assert_eq!(v.len(), 7);
3766 assert_eq!(v, [1, 2, 3, 4, 5, 6, 7]);
3767 }
3768 */
3769
3770 #[test]
3771 fn test_slice_from_mut() {
3772 let mut values = thin_vec![1, 2, 3, 4, 5];
3773 {
3774 let slice = &mut values[2..];
3775 assert!(slice == [3, 4, 5]);
3776 for p in slice {
3777 *p += 2;
3778 }
3779 }
3780
3781 assert!(values == [1, 2, 5, 6, 7]);
3782 }
3783
3784 #[test]
3785 fn test_slice_to_mut() {
3786 let mut values = thin_vec![1, 2, 3, 4, 5];
3787 {
3788 let slice = &mut values[..2];
3789 assert!(slice == [1, 2]);
3790 for p in slice {
3791 *p += 1;
3792 }
3793 }
3794
3795 assert!(values == [2, 3, 3, 4, 5]);
3796 }
3797
3798 #[test]
3799 fn test_split_at_mut() {
3800 let mut values = thin_vec![1, 2, 3, 4, 5];
3801 {
3802 let (left, right) = values.split_at_mut(2);
3803 {
3804 let left: &[_] = left;
3805 assert!(left[..left.len()] == [1, 2]);
3806 }
3807 for p in left {
3808 *p += 1;
3809 }
3810
3811 {
3812 let right: &[_] = right;
3813 assert!(right[..right.len()] == [3, 4, 5]);
3814 }
3815 for p in right {
3816 *p += 2;
3817 }
3818 }
3819
3820 assert_eq!(values, [2, 3, 5, 6, 7]);
3821 }
3822
3823 #[test]
3824 fn test_clone() {
3825 let v: ThinVec<i32> = thin_vec![];
3826 let w = thin_vec![1, 2, 3];
3827
3828 assert_eq!(v, v.clone());
3829
3830 let z = w.clone();
3831 assert_eq!(w, z);
3832 // they should be disjoint in memory.
3833 assert!(w.as_ptr() != z.as_ptr())
3834 }
3835
3836 #[test]
3837 fn test_clone_from() {
3838 let mut v = thin_vec![];
3839 let three: ThinVec<Box<_>> = thin_vec![Box::new(1), Box::new(2), Box::new(3)];
3840 let two: ThinVec<Box<_>> = thin_vec![Box::new(4), Box::new(5)];
3841 // zero, long
3842 v.clone_from(&three);
3843 assert_eq!(v, three);
3844
3845 // equal
3846 v.clone_from(&three);
3847 assert_eq!(v, three);
3848
3849 // long, short
3850 v.clone_from(&two);
3851 assert_eq!(v, two);
3852
3853 // short, long
3854 v.clone_from(&three);
3855 assert_eq!(v, three)
3856 }
3857
3858 #[test]
3859 fn test_retain() {
3860 let mut vec = thin_vec![1, 2, 3, 4];
3861 vec.retain(|&x| x % 2 == 0);
3862 assert_eq!(vec, [2, 4]);
3863 }
3864
3865 #[test]
3866 fn test_retain_mut() {
3867 let mut vec = thin_vec![9, 9, 9, 9];
3868 let mut i = 0;
3869 vec.retain_mut(|x| {
3870 i += 1;
3871 *x = i;
3872 i != 4
3873 });
3874 assert_eq!(vec, [1, 2, 3]);
3875 }
3876
3877 #[test]
3878 fn test_dedup() {
3879 fn case(a: ThinVec<i32>, b: ThinVec<i32>) {
3880 let mut v = a;
3881 v.dedup();
3882 assert_eq!(v, b);
3883 }
3884 case(thin_vec![], thin_vec![]);
3885 case(thin_vec![1], thin_vec![1]);
3886 case(thin_vec![1, 1], thin_vec![1]);
3887 case(thin_vec![1, 2, 3], thin_vec![1, 2, 3]);
3888 case(thin_vec![1, 1, 2, 3], thin_vec![1, 2, 3]);
3889 case(thin_vec![1, 2, 2, 3], thin_vec![1, 2, 3]);
3890 case(thin_vec![1, 2, 3, 3], thin_vec![1, 2, 3]);
3891 case(thin_vec![1, 1, 2, 2, 2, 3, 3], thin_vec![1, 2, 3]);
3892 }
3893
3894 #[test]
3895 fn test_dedup_by_key() {
3896 fn case(a: ThinVec<i32>, b: ThinVec<i32>) {
3897 let mut v = a;
3898 v.dedup_by_key(|i| *i / 10);
3899 assert_eq!(v, b);
3900 }
3901 case(thin_vec![], thin_vec![]);
3902 case(thin_vec![10], thin_vec![10]);
3903 case(thin_vec![10, 11], thin_vec![10]);
3904 case(thin_vec![10, 20, 30], thin_vec![10, 20, 30]);
3905 case(thin_vec![10, 11, 20, 30], thin_vec![10, 20, 30]);
3906 case(thin_vec![10, 20, 21, 30], thin_vec![10, 20, 30]);
3907 case(thin_vec![10, 20, 30, 31], thin_vec![10, 20, 30]);
3908 case(thin_vec![10, 11, 20, 21, 22, 30, 31], thin_vec![10, 20, 30]);
3909 }
3910
3911 #[test]
3912 fn test_dedup_by() {
3913 let mut vec = thin_vec!["foo", "bar", "Bar", "baz", "bar"];
3914 vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
3915
3916 assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
3917
3918 let mut vec = thin_vec![("foo", 1), ("foo", 2), ("bar", 3), ("bar", 4), ("bar", 5)];
3919 vec.dedup_by(|a, b| {
3920 a.0 == b.0 && {
3921 b.1 += a.1;
3922 true
3923 }
3924 });
3925
3926 assert_eq!(vec, [("foo", 3), ("bar", 12)]);
3927 }
3928
3929 #[test]
3930 fn test_dedup_unique() {
3931 let mut v0: ThinVec<Box<_>> = thin_vec![Box::new(1), Box::new(1), Box::new(2), Box::new(3)];
3932 v0.dedup();
3933 let mut v1: ThinVec<Box<_>> = thin_vec![Box::new(1), Box::new(2), Box::new(2), Box::new(3)];
3934 v1.dedup();
3935 let mut v2: ThinVec<Box<_>> = thin_vec![Box::new(1), Box::new(2), Box::new(3), Box::new(3)];
3936 v2.dedup();
3937 // If the boxed pointers were leaked or otherwise misused, valgrind
3938 // and/or rt should raise errors.
3939 }
3940
3941 #[test]
3942 #[cfg_attr(
3943 feature = "gecko-ffi",
3944 should_panic = "ThinVec<T> cannot bridge to nsTArray<T> when T is zero-sized"
3945 )]
3946 fn zero_sized_values() {
3947 let mut v = ThinVec::new();
3948 assert_eq!(v.len(), 0);
3949 v.push(());
3950 assert_eq!(v.len(), 1);
3951 v.push(());
3952 assert_eq!(v.len(), 2);
3953 assert_eq!(v.pop(), Some(()));
3954 assert_eq!(v.pop(), Some(()));
3955 assert_eq!(v.pop(), None);
3956
3957 assert_eq!(v.iter().count(), 0);
3958 v.push(());
3959 assert_eq!(v.iter().count(), 1);
3960 v.push(());
3961 assert_eq!(v.iter().count(), 2);
3962
3963 for &() in &v {}
3964
3965 assert_eq!(v.iter_mut().count(), 2);
3966 v.push(());
3967 assert_eq!(v.iter_mut().count(), 3);
3968 v.push(());
3969 assert_eq!(v.iter_mut().count(), 4);
3970
3971 for &mut () in &mut v {}
3972 unsafe {
3973 v.set_len(0);
3974 }
3975 assert_eq!(v.iter_mut().count(), 0);
3976 }
3977
3978 #[test]
3979 fn test_partition() {
3980 assert_eq!(
3981 thin_vec![].into_iter().partition(|x: &i32| *x < 3),
3982 (thin_vec![], thin_vec![])
3983 );
3984 assert_eq!(
3985 thin_vec![1, 2, 3].into_iter().partition(|x| *x < 4),
3986 (thin_vec![1, 2, 3], thin_vec![])
3987 );
3988 assert_eq!(
3989 thin_vec![1, 2, 3].into_iter().partition(|x| *x < 2),
3990 (thin_vec![1], thin_vec![2, 3])
3991 );
3992 assert_eq!(
3993 thin_vec![1, 2, 3].into_iter().partition(|x| *x < 0),
3994 (thin_vec![], thin_vec![1, 2, 3])
3995 );
3996 }
3997
3998 #[test]
3999 fn test_zip_unzip() {
4000 let z1 = thin_vec![(1, 4), (2, 5), (3, 6)];
4001
4002 let (left, right): (ThinVec<_>, ThinVec<_>) = z1.iter().cloned().unzip();
4003
4004 assert_eq!((1, 4), (left[0], right[0]));
4005 assert_eq!((2, 5), (left[1], right[1]));
4006 assert_eq!((3, 6), (left[2], right[2]));
4007 }
4008
4009 #[test]
4010 fn test_vec_truncate_drop() {
4011 static mut DROPS: u32 = 0;
4012 #[allow(unused)]
4013 struct Elem(i32);
4014 impl Drop for Elem {
4015 fn drop(&mut self) {
4016 unsafe {
4017 DROPS += 1;
4018 }
4019 }
4020 }
4021
4022 let mut v = thin_vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)];
4023 assert_eq!(unsafe { DROPS }, 0);
4024 v.truncate(3);
4025 assert_eq!(unsafe { DROPS }, 2);
4026 v.truncate(0);
4027 assert_eq!(unsafe { DROPS }, 5);
4028 }
4029
4030 #[test]
4031 #[should_panic]
4032 fn test_vec_truncate_fail() {
4033 struct BadElem(i32);
4034 impl Drop for BadElem {
4035 fn drop(&mut self) {
4036 let BadElem(ref mut x) = *self;
4037 if *x == 0xbadbeef {
4038 panic!("BadElem panic: 0xbadbeef")
4039 }
4040 }
4041 }
4042
4043 let mut v = thin_vec![BadElem(1), BadElem(2), BadElem(0xbadbeef), BadElem(4)];
4044 v.truncate(0);
4045 }
4046
4047 #[test]
4048 fn test_index() {
4049 let vec = thin_vec![1, 2, 3];
4050 assert!(vec[1] == 2);
4051 }
4052
4053 #[test]
4054 #[should_panic]
4055 fn test_index_out_of_bounds() {
4056 let vec = thin_vec![1, 2, 3];
4057 let _ = vec[3];
4058 }
4059
4060 #[test]
4061 #[should_panic]
4062 fn test_slice_out_of_bounds_1() {
4063 let x = thin_vec![1, 2, 3, 4, 5];
4064 let _ = &x[!0..];
4065 }
4066
4067 #[test]
4068 #[should_panic]
4069 fn test_slice_out_of_bounds_2() {
4070 let x = thin_vec![1, 2, 3, 4, 5];
4071 let _ = &x[..6];
4072 }
4073
4074 #[test]
4075 #[should_panic]
4076 fn test_slice_out_of_bounds_3() {
4077 let x = thin_vec![1, 2, 3, 4, 5];
4078 let _ = &x[!0..4];
4079 }
4080
4081 #[test]
4082 #[should_panic]
4083 fn test_slice_out_of_bounds_4() {
4084 let x = thin_vec![1, 2, 3, 4, 5];
4085 let _ = &x[1..6];
4086 }
4087
4088 #[test]
4089 #[should_panic]
4090 fn test_slice_out_of_bounds_5() {
4091 let x = thin_vec![1, 2, 3, 4, 5];
4092 let _ = &x[3..2];
4093 }
4094
4095 #[test]
4096 #[should_panic]
4097 fn test_swap_remove_empty() {
4098 let mut vec = ThinVec::<i32>::new();
4099 vec.swap_remove(0);
4100 }
4101
4102 #[test]
4103 fn test_move_items() {
4104 let vec = thin_vec![1, 2, 3];
4105 let mut vec2 = thin_vec![];
4106 for i in vec {
4107 vec2.push(i);
4108 }
4109 assert_eq!(vec2, [1, 2, 3]);
4110 }
4111
4112 #[test]
4113 fn test_move_items_reverse() {
4114 let vec = thin_vec![1, 2, 3];
4115 let mut vec2 = thin_vec![];
4116 for i in vec.into_iter().rev() {
4117 vec2.push(i);
4118 }
4119 assert_eq!(vec2, [3, 2, 1]);
4120 }
4121
4122 #[test]
4123 #[cfg_attr(
4124 feature = "gecko-ffi",
4125 should_panic = "ThinVec<T> cannot bridge to nsTArray<T> when T is zero-sized"
4126 )]
4127 fn test_move_items_zero_sized() {
4128 let vec = thin_vec![(), (), ()];
4129 let mut vec2 = thin_vec![];
4130 for i in vec {
4131 vec2.push(i);
4132 }
4133 assert_eq!(vec2, [(), (), ()]);
4134 }
4135
4136 #[test]
4137 fn test_drain_items() {
4138 let mut vec = thin_vec![1, 2, 3];
4139 let mut vec2 = thin_vec![];
4140 for i in vec.drain(..) {
4141 vec2.push(i);
4142 }
4143 assert_eq!(vec, []);
4144 assert_eq!(vec2, [1, 2, 3]);
4145 }
4146
4147 #[test]
4148 fn test_drain_items_reverse() {
4149 let mut vec = thin_vec![1, 2, 3];
4150 let mut vec2 = thin_vec![];
4151 for i in vec.drain(..).rev() {
4152 vec2.push(i);
4153 }
4154 assert_eq!(vec, []);
4155 assert_eq!(vec2, [3, 2, 1]);
4156 }
4157
4158 #[test]
4159 #[cfg_attr(
4160 feature = "gecko-ffi",
4161 should_panic = "ThinVec<T> cannot bridge to nsTArray<T> when T is zero-sized"
4162 )]
4163 fn test_drain_items_zero_sized() {
4164 let mut vec = thin_vec![(), (), ()];
4165 let mut vec2 = thin_vec![];
4166 for i in vec.drain(..) {
4167 vec2.push(i);
4168 }
4169 assert_eq!(vec, []);
4170 assert_eq!(vec2, [(), (), ()]);
4171 }
4172
4173 #[test]
4174 #[should_panic]
4175 fn test_drain_out_of_bounds() {
4176 let mut v = thin_vec![1, 2, 3, 4, 5];
4177 v.drain(5..6);
4178 }
4179
4180 #[test]
4181 fn test_drain_range() {
4182 let mut v = thin_vec![1, 2, 3, 4, 5];
4183 for _ in v.drain(4..) {}
4184 assert_eq!(v, &[1, 2, 3, 4]);
4185
4186 let mut v: ThinVec<_> = (1..6).map(|x| x.to_string()).collect();
4187 for _ in v.drain(1..4) {}
4188 assert_eq!(v, &[1.to_string(), 5.to_string()]);
4189
4190 let mut v: ThinVec<_> = (1..6).map(|x| x.to_string()).collect();
4191 for _ in v.drain(1..4).rev() {}
4192 assert_eq!(v, &[1.to_string(), 5.to_string()]);
4193 }
4194
4195 #[test]
4196 #[cfg_attr(
4197 feature = "gecko-ffi",
4198 should_panic = "ThinVec<T> cannot bridge to nsTArray<T> when T is zero-sized"
4199 )]
4200 fn test_drain_range_zst() {
4201 let mut v: ThinVec<_> = thin_vec![(); 5];
4202 for _ in v.drain(1..4).rev() {}
4203 assert_eq!(v, &[(), ()]);
4204 }
4205
4206 #[test]
4207 fn test_drain_inclusive_range() {
4208 let mut v = thin_vec!['a', 'b', 'c', 'd', 'e'];
4209 for _ in v.drain(1..=3) {}
4210 assert_eq!(v, &['a', 'e']);
4211
4212 let mut v: ThinVec<_> = (0..=5).map(|x| x.to_string()).collect();
4213 for _ in v.drain(1..=5) {}
4214 assert_eq!(v, &["0".to_string()]);
4215
4216 let mut v: ThinVec<String> = (0..=5).map(|x| x.to_string()).collect();
4217 for _ in v.drain(0..=5) {}
4218 assert_eq!(v, ThinVec::<String>::new());
4219
4220 let mut v: ThinVec<_> = (0..=5).map(|x| x.to_string()).collect();
4221 for _ in v.drain(0..=3) {}
4222 assert_eq!(v, &["4".to_string(), "5".to_string()]);
4223
4224 let mut v: ThinVec<_> = (0..=1).map(|x| x.to_string()).collect();
4225 for _ in v.drain(..=0) {}
4226 assert_eq!(v, &["1".to_string()]);
4227 }
4228
4229 #[test]
4230 #[cfg(not(feature = "gecko-ffi"))]
4231 fn test_drain_max_vec_size() {
4232 let mut v = ThinVec::<()>::with_capacity(MAX_CAP);
4233 unsafe {
4234 v.set_len(MAX_CAP);
4235 }
4236 for _ in v.drain(MAX_CAP - 1..) {}
4237 assert_eq!(v.len(), MAX_CAP - 1);
4238
4239 let mut v = ThinVec::<()>::with_capacity(MAX_CAP);
4240 unsafe {
4241 v.set_len(MAX_CAP);
4242 }
4243 for _ in v.drain(MAX_CAP - 1..=MAX_CAP - 1) {}
4244 assert_eq!(v.len(), MAX_CAP - 1);
4245 }
4246
4247 #[test]
4248 #[should_panic]
4249 fn test_drain_inclusive_out_of_bounds() {
4250 let mut v = thin_vec![1, 2, 3, 4, 5];
4251 v.drain(5..=5);
4252 }
4253
4254 #[test]
4255 fn test_splice() {
4256 let mut v = thin_vec![1, 2, 3, 4, 5];
4257 let a = [10, 11, 12];
4258 v.splice(2..4, a.iter().cloned());
4259 assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
4260 v.splice(1..3, Some(20));
4261 assert_eq!(v, &[1, 20, 11, 12, 5]);
4262 }
4263
4264 #[test]
4265 fn test_splice_inclusive_range() {
4266 let mut v = thin_vec![1, 2, 3, 4, 5];
4267 let a = [10, 11, 12];
4268 let t1: ThinVec<_> = v.splice(2..=3, a.iter().cloned()).collect();
4269 assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
4270 assert_eq!(t1, &[3, 4]);
4271 let t2: ThinVec<_> = v.splice(1..=2, Some(20)).collect();
4272 assert_eq!(v, &[1, 20, 11, 12, 5]);
4273 assert_eq!(t2, &[2, 10]);
4274 }
4275
4276 #[test]
4277 #[should_panic]
4278 fn test_splice_out_of_bounds() {
4279 let mut v = thin_vec![1, 2, 3, 4, 5];
4280 let a = [10, 11, 12];
4281 v.splice(5..6, a.iter().cloned());
4282 }
4283
4284 #[test]
4285 #[should_panic]
4286 fn test_splice_inclusive_out_of_bounds() {
4287 let mut v = thin_vec![1, 2, 3, 4, 5];
4288 let a = [10, 11, 12];
4289 v.splice(5..=5, a.iter().cloned());
4290 }
4291
4292 #[test]
4293 #[cfg_attr(
4294 feature = "gecko-ffi",
4295 should_panic = "ThinVec<T> cannot bridge to nsTArray<T> when T is zero-sized"
4296 )]
4297 fn test_splice_items_zero_sized() {
4298 let mut vec = thin_vec![(), (), ()];
4299 let vec2 = thin_vec![];
4300 let t: ThinVec<_> = vec.splice(1..2, vec2.iter().cloned()).collect();
4301 assert_eq!(vec, &[(), ()]);
4302 assert_eq!(t, &[()]);
4303 }
4304
4305 #[test]
4306 fn test_splice_unbounded() {
4307 let mut vec = thin_vec![1, 2, 3, 4, 5];
4308 let t: ThinVec<_> = vec.splice(.., None).collect();
4309 assert_eq!(vec, &[]);
4310 assert_eq!(t, &[1, 2, 3, 4, 5]);
4311 }
4312
4313 #[test]
4314 fn test_splice_forget() {
4315 let mut v = thin_vec![1, 2, 3, 4, 5];
4316 let a = [10, 11, 12];
4317 ::core::mem::forget(v.splice(2..4, a.iter().cloned()));
4318 assert_eq!(v, &[1, 2]);
4319 }
4320
4321 #[test]
4322 fn test_splice_from_empty() {
4323 let mut v = thin_vec![];
4324 let a = [10, 11, 12];
4325 v.splice(.., a.iter().cloned());
4326 assert_eq!(v, &[10, 11, 12]);
4327 }
4328
4329 /* probs won't ever impl this
4330 #[test]
4331 fn test_into_boxed_slice() {
4332 let xs = thin_vec![1, 2, 3];
4333 let ys = xs.into_boxed_slice();
4334 assert_eq!(&*ys, [1, 2, 3]);
4335 }
4336 */
4337
4338 #[test]
4339 fn test_append() {
4340 let mut vec = thin_vec![1, 2, 3];
4341 let mut vec2 = thin_vec![4, 5, 6];
4342 vec.append(&mut vec2);
4343 assert_eq!(vec, [1, 2, 3, 4, 5, 6]);
4344 assert_eq!(vec2, []);
4345 }
4346
4347 #[test]
4348 fn test_split_off() {
4349 let mut vec = thin_vec![1, 2, 3, 4, 5, 6];
4350 let vec2 = vec.split_off(4);
4351 assert_eq!(vec, [1, 2, 3, 4]);
4352 assert_eq!(vec2, [5, 6]);
4353 }
4354
4355 #[test]
4356 fn test_into_iter_as_slice() {
4357 let vec = thin_vec!['a', 'b', 'c'];
4358 let mut into_iter = vec.into_iter();
4359 assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
4360 let _ = into_iter.next().unwrap();
4361 assert_eq!(into_iter.as_slice(), &['b', 'c']);
4362 let _ = into_iter.next().unwrap();
4363 let _ = into_iter.next().unwrap();
4364 assert_eq!(into_iter.as_slice(), &[]);
4365 }
4366
4367 #[test]
4368 fn test_into_iter_as_mut_slice() {
4369 let vec = thin_vec!['a', 'b', 'c'];
4370 let mut into_iter = vec.into_iter();
4371 assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
4372 into_iter.as_mut_slice()[0] = 'x';
4373 into_iter.as_mut_slice()[1] = 'y';
4374 assert_eq!(into_iter.next().unwrap(), 'x');
4375 assert_eq!(into_iter.as_slice(), &['y', 'c']);
4376 }
4377
4378 #[test]
4379 fn test_into_iter_debug() {
4380 let vec = thin_vec!['a', 'b', 'c'];
4381 let into_iter = vec.into_iter();
4382 let debug = format!("{:?}", into_iter);
4383 assert_eq!(debug, "IntoIter(['a', 'b', 'c'])");
4384 }
4385
4386 #[test]
4387 fn test_into_iter_count() {
4388 assert_eq!(thin_vec![1, 2, 3].into_iter().count(), 3);
4389 }
4390
4391 #[test]
4392 fn test_into_iter_clone() {
4393 fn iter_equal<I: Iterator<Item = i32>>(it: I, slice: &[i32]) {
4394 let v: ThinVec<i32> = it.collect();
4395 assert_eq!(&v[..], slice);
4396 }
4397 let mut it = thin_vec![1, 2, 3].into_iter();
4398 iter_equal(it.clone(), &[1, 2, 3]);
4399 assert_eq!(it.next(), Some(1));
4400 let mut it = it.rev();
4401 iter_equal(it.clone(), &[3, 2]);
4402 assert_eq!(it.next(), Some(3));
4403 iter_equal(it.clone(), &[2]);
4404 assert_eq!(it.next(), Some(2));
4405 iter_equal(it.clone(), &[]);
4406 assert_eq!(it.next(), None);
4407 }
4408
4409 #[allow(dead_code)]
4410 fn assert_covariance() {
4411 fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
4412 d
4413 }
4414 fn into_iter<'new>(i: IntoIter<&'static str>) -> IntoIter<&'new str> {
4415 i
4416 }
4417 }
4418
4419 /* TODO: specialize vec.into_iter().collect::<ThinVec<_>>();
4420 #[test]
4421 fn from_into_inner() {
4422 let vec = thin_vec![1, 2, 3];
4423 let ptr = vec.as_ptr();
4424 let vec = vec.into_iter().collect::<ThinVec<_>>();
4425 assert_eq!(vec, [1, 2, 3]);
4426 assert_eq!(vec.as_ptr(), ptr);
4427
4428 let ptr = &vec[1] as *const _;
4429 let mut it = vec.into_iter();
4430 it.next().unwrap();
4431 let vec = it.collect::<ThinVec<_>>();
4432 assert_eq!(vec, [2, 3]);
4433 assert!(ptr != vec.as_ptr());
4434 }
4435 */
4436
4437 #[test]
4438 #[cfg_attr(feature = "gecko-ffi", ignore)]
4439 fn overaligned_allocations() {
4440 #[repr(align(256))]
4441 struct Foo(usize);
4442 let mut v = thin_vec![Foo(273)];
4443 for i in 0..0x1000 {
4444 v.reserve_exact(i);
4445 assert!(v[0].0 == 273);
4446 assert!(v.as_ptr() as usize & 0xff == 0);
4447 v.shrink_to_fit();
4448 assert!(v[0].0 == 273);
4449 assert!(v.as_ptr() as usize & 0xff == 0);
4450 }
4451 }
4452
4453 /* TODO: implement drain_filter?
4454 #[test]
4455 fn drain_filter_empty() {
4456 let mut vec: ThinVec<i32> = thin_vec![];
4457
4458 {
4459 let mut iter = vec.drain_filter(|_| true);
4460 assert_eq!(iter.size_hint(), (0, Some(0)));
4461 assert_eq!(iter.next(), None);
4462 assert_eq!(iter.size_hint(), (0, Some(0)));
4463 assert_eq!(iter.next(), None);
4464 assert_eq!(iter.size_hint(), (0, Some(0)));
4465 }
4466 assert_eq!(vec.len(), 0);
4467 assert_eq!(vec, thin_vec![]);
4468 }
4469
4470 #[test]
4471 fn drain_filter_zst() {
4472 let mut vec = thin_vec![(), (), (), (), ()];
4473 let initial_len = vec.len();
4474 let mut count = 0;
4475 {
4476 let mut iter = vec.drain_filter(|_| true);
4477 assert_eq!(iter.size_hint(), (0, Some(initial_len)));
4478 while let Some(_) = iter.next() {
4479 count += 1;
4480 assert_eq!(iter.size_hint(), (0, Some(initial_len - count)));
4481 }
4482 assert_eq!(iter.size_hint(), (0, Some(0)));
4483 assert_eq!(iter.next(), None);
4484 assert_eq!(iter.size_hint(), (0, Some(0)));
4485 }
4486
4487 assert_eq!(count, initial_len);
4488 assert_eq!(vec.len(), 0);
4489 assert_eq!(vec, thin_vec![]);
4490 }
4491
4492 #[test]
4493 fn drain_filter_false() {
4494 let mut vec = thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
4495
4496 let initial_len = vec.len();
4497 let mut count = 0;
4498 {
4499 let mut iter = vec.drain_filter(|_| false);
4500 assert_eq!(iter.size_hint(), (0, Some(initial_len)));
4501 for _ in iter.by_ref() {
4502 count += 1;
4503 }
4504 assert_eq!(iter.size_hint(), (0, Some(0)));
4505 assert_eq!(iter.next(), None);
4506 assert_eq!(iter.size_hint(), (0, Some(0)));
4507 }
4508
4509 assert_eq!(count, 0);
4510 assert_eq!(vec.len(), initial_len);
4511 assert_eq!(vec, thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
4512 }
4513
4514 #[test]
4515 fn drain_filter_true() {
4516 let mut vec = thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
4517
4518 let initial_len = vec.len();
4519 let mut count = 0;
4520 {
4521 let mut iter = vec.drain_filter(|_| true);
4522 assert_eq!(iter.size_hint(), (0, Some(initial_len)));
4523 while let Some(_) = iter.next() {
4524 count += 1;
4525 assert_eq!(iter.size_hint(), (0, Some(initial_len - count)));
4526 }
4527 assert_eq!(iter.size_hint(), (0, Some(0)));
4528 assert_eq!(iter.next(), None);
4529 assert_eq!(iter.size_hint(), (0, Some(0)));
4530 }
4531
4532 assert_eq!(count, initial_len);
4533 assert_eq!(vec.len(), 0);
4534 assert_eq!(vec, thin_vec![]);
4535 }
4536
4537 #[test]
4538 fn drain_filter_complex() {
4539
4540 { // [+xxx++++++xxxxx++++x+x++]
4541 let mut vec = thin_vec![1,
4542 2, 4, 6,
4543 7, 9, 11, 13, 15, 17,
4544 18, 20, 22, 24, 26,
4545 27, 29, 31, 33,
4546 34,
4547 35,
4548 36,
4549 37, 39];
4550
4551 let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<ThinVec<_>>();
4552 assert_eq!(removed.len(), 10);
4553 assert_eq!(removed, thin_vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
4554
4555 assert_eq!(vec.len(), 14);
4556 assert_eq!(vec, thin_vec![1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]);
4557 }
4558
4559 { // [xxx++++++xxxxx++++x+x++]
4560 let mut vec = thin_vec![2, 4, 6,
4561 7, 9, 11, 13, 15, 17,
4562 18, 20, 22, 24, 26,
4563 27, 29, 31, 33,
4564 34,
4565 35,
4566 36,
4567 37, 39];
4568
4569 let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<ThinVec<_>>();
4570 assert_eq!(removed.len(), 10);
4571 assert_eq!(removed, thin_vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
4572
4573 assert_eq!(vec.len(), 13);
4574 assert_eq!(vec, thin_vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]);
4575 }
4576
4577 { // [xxx++++++xxxxx++++x+x]
4578 let mut vec = thin_vec![2, 4, 6,
4579 7, 9, 11, 13, 15, 17,
4580 18, 20, 22, 24, 26,
4581 27, 29, 31, 33,
4582 34,
4583 35,
4584 36];
4585
4586 let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<ThinVec<_>>();
4587 assert_eq!(removed.len(), 10);
4588 assert_eq!(removed, thin_vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
4589
4590 assert_eq!(vec.len(), 11);
4591 assert_eq!(vec, thin_vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35]);
4592 }
4593
4594 { // [xxxxxxxxxx+++++++++++]
4595 let mut vec = thin_vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
4596 1, 3, 5, 7, 9, 11, 13, 15, 17, 19];
4597
4598 let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<ThinVec<_>>();
4599 assert_eq!(removed.len(), 10);
4600 assert_eq!(removed, thin_vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);
4601
4602 assert_eq!(vec.len(), 10);
4603 assert_eq!(vec, thin_vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
4604 }
4605
4606 { // [+++++++++++xxxxxxxxxx]
4607 let mut vec = thin_vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19,
4608 2, 4, 6, 8, 10, 12, 14, 16, 18, 20];
4609
4610 let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<ThinVec<_>>();
4611 assert_eq!(removed.len(), 10);
4612 assert_eq!(removed, thin_vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);
4613
4614 assert_eq!(vec.len(), 10);
4615 assert_eq!(vec, thin_vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
4616 }
4617 }
4618 */
4619 #[test]
4620 fn test_reserve_exact() {
4621 // This is all the same as test_reserve
4622
4623 let mut v = ThinVec::new();
4624 assert_eq!(v.capacity(), 0);
4625
4626 v.reserve_exact(2);
4627 assert!(v.capacity() >= 2);
4628
4629 for i in 0..16 {
4630 v.push(i);
4631 }
4632
4633 assert!(v.capacity() >= 16);
4634 v.reserve_exact(16);
4635 assert!(v.capacity() >= 32);
4636
4637 v.push(16);
4638
4639 v.reserve_exact(16);
4640 assert!(v.capacity() >= 33)
4641 }
4642
4643 /* TODO: implement try_reserve
4644 #[test]
4645 fn test_try_reserve() {
4646
4647 // These are the interesting cases:
4648 // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM)
4649 // * > isize::MAX should always fail
4650 // * On 16/32-bit should CapacityOverflow
4651 // * On 64-bit should OOM
4652 // * overflow may trigger when adding `len` to `cap` (in number of elements)
4653 // * overflow may trigger when multiplying `new_cap` by size_of::<T> (to get bytes)
4654
4655 const MAX_CAP: usize = isize::MAX as usize;
4656 const MAX_USIZE: usize = usize::MAX;
4657
4658 // On 16/32-bit, we check that allocations don't exceed isize::MAX,
4659 // on 64-bit, we assume the OS will give an OOM for such a ridiculous size.
4660 // Any platform that succeeds for these requests is technically broken with
4661 // ptr::offset because LLVM is the worst.
4662 let guards_against_isize = size_of::<usize>() < 8;
4663
4664 {
4665 // Note: basic stuff is checked by test_reserve
4666 let mut empty_bytes: ThinVec<u8> = ThinVec::new();
4667
4668 // Check isize::MAX doesn't count as an overflow
4669 if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) {
4670 panic!("isize::MAX shouldn't trigger an overflow!");
4671 }
4672 // Play it again, frank! (just to be sure)
4673 if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) {
4674 panic!("isize::MAX shouldn't trigger an overflow!");
4675 }
4676
4677 if guards_against_isize {
4678 // Check isize::MAX + 1 does count as overflow
4679 if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP + 1) {
4680 } else { panic!("isize::MAX + 1 should trigger an overflow!") }
4681
4682 // Check usize::MAX does count as overflow
4683 if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) {
4684 } else { panic!("usize::MAX should trigger an overflow!") }
4685 } else {
4686 // Check isize::MAX + 1 is an OOM
4687 if let Err(AllocErr) = empty_bytes.try_reserve(MAX_CAP + 1) {
4688 } else { panic!("isize::MAX + 1 should trigger an OOM!") }
4689
4690 // Check usize::MAX is an OOM
4691 if let Err(AllocErr) = empty_bytes.try_reserve(MAX_USIZE) {
4692 } else { panic!("usize::MAX should trigger an OOM!") }
4693 }
4694 }
4695
4696
4697 {
4698 // Same basic idea, but with non-zero len
4699 let mut ten_bytes: ThinVec<u8> = thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
4700
4701 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) {
4702 panic!("isize::MAX shouldn't trigger an overflow!");
4703 }
4704 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) {
4705 panic!("isize::MAX shouldn't trigger an overflow!");
4706 }
4707 if guards_against_isize {
4708 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) {
4709 } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
4710 } else {
4711 if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) {
4712 } else { panic!("isize::MAX + 1 should trigger an OOM!") }
4713 }
4714 // Should always overflow in the add-to-len
4715 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) {
4716 } else { panic!("usize::MAX should trigger an overflow!") }
4717 }
4718
4719
4720 {
4721 // Same basic idea, but with interesting type size
4722 let mut ten_u32s: ThinVec<u32> = thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
4723
4724 if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 10) {
4725 panic!("isize::MAX shouldn't trigger an overflow!");
4726 }
4727 if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 10) {
4728 panic!("isize::MAX shouldn't trigger an overflow!");
4729 }
4730 if guards_against_isize {
4731 if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
4732 } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
4733 } else {
4734 if let Err(AllocErr) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
4735 } else { panic!("isize::MAX + 1 should trigger an OOM!") }
4736 }
4737 // Should fail in the mul-by-size
4738 if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_USIZE - 20) {
4739 } else {
4740 panic!("usize::MAX should trigger an overflow!");
4741 }
4742 }
4743
4744 }
4745
4746 #[test]
4747 fn test_try_reserve_exact() {
4748
4749 // This is exactly the same as test_try_reserve with the method changed.
4750 // See that test for comments.
4751
4752 const MAX_CAP: usize = isize::MAX as usize;
4753 const MAX_USIZE: usize = usize::MAX;
4754
4755 let guards_against_isize = size_of::<usize>() < 8;
4756
4757 {
4758 let mut empty_bytes: ThinVec<u8> = ThinVec::new();
4759
4760 if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) {
4761 panic!("isize::MAX shouldn't trigger an overflow!");
4762 }
4763 if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) {
4764 panic!("isize::MAX shouldn't trigger an overflow!");
4765 }
4766
4767 if guards_against_isize {
4768 if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP + 1) {
4769 } else { panic!("isize::MAX + 1 should trigger an overflow!") }
4770
4771 if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_USIZE) {
4772 } else { panic!("usize::MAX should trigger an overflow!") }
4773 } else {
4774 if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_CAP + 1) {
4775 } else { panic!("isize::MAX + 1 should trigger an OOM!") }
4776
4777 if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_USIZE) {
4778 } else { panic!("usize::MAX should trigger an OOM!") }
4779 }
4780 }
4781
4782
4783 {
4784 let mut ten_bytes: ThinVec<u8> = thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
4785
4786 if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) {
4787 panic!("isize::MAX shouldn't trigger an overflow!");
4788 }
4789 if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) {
4790 panic!("isize::MAX shouldn't trigger an overflow!");
4791 }
4792 if guards_against_isize {
4793 if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
4794 } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
4795 } else {
4796 if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
4797 } else { panic!("isize::MAX + 1 should trigger an OOM!") }
4798 }
4799 if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) {
4800 } else { panic!("usize::MAX should trigger an overflow!") }
4801 }
4802
4803
4804 {
4805 let mut ten_u32s: ThinVec<u32> = thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
4806
4807 if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 10) {
4808 panic!("isize::MAX shouldn't trigger an overflow!");
4809 }
4810 if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 10) {
4811 panic!("isize::MAX shouldn't trigger an overflow!");
4812 }
4813 if guards_against_isize {
4814 if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
4815 } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
4816 } else {
4817 if let Err(AllocErr) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
4818 } else { panic!("isize::MAX + 1 should trigger an OOM!") }
4819 }
4820 if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) {
4821 } else { panic!("usize::MAX should trigger an overflow!") }
4822 }
4823 }
4824 */
4825
4826 #[cfg(feature = "gecko-ffi")]
4827 #[test]
4828 fn auto_t_array_basic() {
4829 crate::auto_thin_vec!(let t: [u8; 10]);
4830 assert_eq!(t.capacity(), 10);
4831 assert!(t.is_auto_array());
4832 assert!(t.uses_stack_allocated_buffer());
4833 assert!(!t.has_allocation());
4834 assert_eq!(t.len(), 0);
4835 {
4836 let inner = unsafe { &mut *t.as_mut().as_mut_ptr() };
4837 for i in 0..30 {
4838 inner.push(i as u8);
4839 }
4840 }
4841
4842 assert!(t.is_auto_array());
4843 assert!(!t.uses_stack_allocated_buffer());
4844 assert_eq!(t.len(), 30);
4845 assert!(t.has_allocation());
4846 assert_eq!(t[5], 5);
4847 assert_eq!(t[29], 29);
4848 assert!(t.capacity() >= 30);
4849
4850 {
4851 let inner = unsafe { &mut *t.as_mut().as_mut_ptr() };
4852 inner.truncate(5);
4853 }
4854
4855 assert_eq!(t.len(), 5);
4856 assert!(t.capacity() >= 30);
4857 assert!(t.has_allocation());
4858 t.as_mut().shrink_to_fit();
4859 assert!(!t.has_allocation());
4860 assert!(t.is_auto_array());
4861 assert!(t.uses_stack_allocated_buffer());
4862 assert_eq!(t.capacity(), 10);
4863 }
4864
4865 #[test]
4866 #[cfg_attr(feature = "gecko-ffi", ignore)]
4867 fn test_header_data() {
4868 macro_rules! assert_aligned_head_ptr {
4869 ($typename:ty) => {{
4870 let v: ThinVec<$typename> = ThinVec::with_capacity(1 /* ensure allocation */);
4871 let head_ptr: *mut $typename = v.data_raw();
4872 assert_eq!(
4873 head_ptr as usize % core::mem::align_of::<$typename>(),
4874 0,
4875 "expected Header::data<{}> to be aligned",
4876 stringify!($typename)
4877 );
4878 }};
4879 }
4880
4881 const HEADER_SIZE: usize = core::mem::size_of::<Header>();
4882 assert_eq!(2 * core::mem::size_of::<usize>(), HEADER_SIZE);
4883
4884 #[repr(C, align(128))]
4885 struct Funky<T>(T);
4886 assert_eq!(padding::<Funky<()>>(), 128 - HEADER_SIZE);
4887 assert_aligned_head_ptr!(Funky<()>);
4888
4889 assert_eq!(padding::<Funky<u8>>(), 128 - HEADER_SIZE);
4890 assert_aligned_head_ptr!(Funky<u8>);
4891
4892 assert_eq!(padding::<Funky<[(); 1024]>>(), 128 - HEADER_SIZE);
4893 assert_aligned_head_ptr!(Funky<[(); 1024]>);
4894
4895 assert_eq!(padding::<Funky<[*mut usize; 1024]>>(), 128 - HEADER_SIZE);
4896 assert_aligned_head_ptr!(Funky<[*mut usize; 1024]>);
4897 }
4898
4899 #[cfg(feature = "serde")]
4900 use serde_test::{Token, assert_tokens};
4901
4902 #[test]
4903 #[cfg(feature = "serde")]
4904 fn test_ser_de_empty() {
4905 let vec = ThinVec::<u32>::new();
4906
4907 assert_tokens(&vec, &[Token::Seq { len: Some(0) }, Token::SeqEnd]);
4908 }
4909
4910 #[test]
4911 #[cfg(feature = "serde")]
4912 fn test_ser_de() {
4913 let mut vec = ThinVec::<u32>::new();
4914 vec.push(20);
4915 vec.push(55);
4916 vec.push(123);
4917
4918 assert_tokens(
4919 &vec,
4920 &[
4921 Token::Seq { len: Some(3) },
4922 Token::U32(20),
4923 Token::U32(55),
4924 Token::U32(123),
4925 Token::SeqEnd,
4926 ],
4927 );
4928 }
4929
4930 #[test]
4931 fn test_set_len() {
4932 let mut vec: ThinVec<u32> = thin_vec![];
4933 unsafe {
4934 vec.set_len(0); // at one point this caused a crash
4935 }
4936 }
4937
4938 #[test]
4939 #[should_panic(expected = "invalid set_len(1) on empty ThinVec")]
4940 fn test_set_len_invalid() {
4941 let mut vec: ThinVec<u32> = thin_vec![];
4942 unsafe {
4943 vec.set_len(1);
4944 }
4945 }
4946
4947 #[test]
4948 #[should_panic(expected = "capacity overflow")]
4949 fn test_capacity_overflow_header_too_big() {
4950 let vec: ThinVec<u8> = ThinVec::with_capacity(isize::MAX as usize - 2);
4951 assert!(vec.capacity() > 0);
4952 }
4953 #[test]
4954 #[should_panic(expected = "capacity overflow")]
4955 fn test_capacity_overflow_cap_too_big() {
4956 let vec: ThinVec<u8> = ThinVec::with_capacity(isize::MAX as usize + 1);
4957 assert!(vec.capacity() > 0);
4958 }
4959 #[test]
4960 #[should_panic(expected = "capacity overflow")]
4961 fn test_capacity_overflow_size_mul1() {
4962 let vec: ThinVec<u16> = ThinVec::with_capacity(isize::MAX as usize + 1);
4963 assert!(vec.capacity() > 0);
4964 }
4965 #[test]
4966 #[should_panic(expected = "capacity overflow")]
4967 fn test_capacity_overflow_size_mul2() {
4968 let vec: ThinVec<u16> = ThinVec::with_capacity(isize::MAX as usize / 2 + 1);
4969 assert!(vec.capacity() > 0);
4970 }
4971 #[test]
4972 #[should_panic(expected = "capacity overflow")]
4973 fn test_capacity_overflow_cap_really_isnt_isize() {
4974 let vec: ThinVec<u8> = ThinVec::with_capacity(isize::MAX as usize);
4975 assert!(vec.capacity() > 0);
4976 }
4977
4978 struct PanicBomb(&'static str);
4979
4980 impl Drop for PanicBomb {
4981 fn drop(&mut self) {
4982 if self.0 == "panic" {
4983 panic!("panic!");
4984 }
4985 }
4986 }
4987
4988 #[test]
4989 #[should_panic(expected = "panic!")]
4990 fn test_panic_into_iter() {
4991 let mut v = ThinVec::new();
4992 v.push(PanicBomb("normal1"));
4993 v.push(PanicBomb("panic"));
4994 v.push(PanicBomb("normal2"));
4995
4996 let mut iter = v.into_iter();
4997 iter.next();
4998 }
4999
5000 #[test]
5001 #[should_panic(expected = "panic!")]
5002 fn test_panic_clear() {
5003 let mut v = ThinVec::new();
5004 v.push(PanicBomb("normal1"));
5005 v.push(PanicBomb("panic"));
5006 v.push(PanicBomb("normal2"));
5007 v.clear();
5008 }
5009
5010 #[cfg(all(feature = "gecko-ffi", feature = "malloc_size_of"))]
5011 #[test]
5012 fn malloc_size_of_auto_array() {
5013 use malloc_size_of::{MallocShallowSizeOf, MallocSizeOfOps};
5014 use std::ffi::c_void;
5015
5016 extern "C" {
5017 fn malloc_usable_size(ptr: *const c_void) -> usize;
5018 }
5019
5020 unsafe extern "C" fn malloc_size_of(ptr: *const c_void) -> usize {
5021 unsafe { malloc_usable_size(ptr) }
5022 }
5023
5024 crate::auto_thin_vec!(let t: [u8; 4]);
5025 let mut ops = MallocSizeOfOps::new(malloc_size_of, None, None);
5026 let _ = MallocShallowSizeOf::shallow_size_of(&**t, &mut ops);
5027 }
5028}