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