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