Skip to main content

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}