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 std::mem::size_of::<Self>(),
2142 std::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: std::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 std::mem::align_of::<T>() <= 8,
2885 "Can't handle alignments greater than 8"
2886 );
2887 assert_eq!(std::mem::offset_of!(Self, buffer), AUTO_ARRAY_HEADER_OFFSET);
2888 Self {
2889 inner: ThinVec::new(),
2890 buffer: AutoBuffer {
2891 header: Header {
2892 _len: 0,
2893 _cap: pack_capacity_and_auto(N as SizeType, true),
2894 },
2895 buffer: mem::MaybeUninit::uninit(),
2896 },
2897 _pinned: std::marker::PhantomPinned,
2898 }
2899 }
2900
2901 /// Returns a raw pointer to the inner ThinVec. Note that if you dereference it from rust, you
2902 /// need to make sure not to move the ThinVec manually via something like
2903 /// `std::mem::take(&mut auto_vec)`.
2904 pub fn as_mut_ptr(self: std::pin::Pin<&mut Self>) -> *mut ThinVec<T> {
2905 debug_assert!(self.is_auto_array());
2906 unsafe { &mut self.get_unchecked_mut().inner }
2907 }
2908
2909 #[inline]
2910 pub unsafe fn shrink_to_fit_known_singleton(self: std::pin::Pin<&mut Self>) {
2911 debug_assert!(self.is_singleton());
2912 let this = unsafe { self.get_unchecked_mut() };
2913 this.buffer.header.set_len(0);
2914 // TODO(emilio): Use NonNull::from_mut when msrv allows.
2915 this.inner.ptr = NonNull::new_unchecked(&mut this.buffer.header);
2916 debug_assert!(this.inner.is_auto_array());
2917 debug_assert!(this.inner.uses_stack_allocated_buffer());
2918 }
2919
2920 pub fn shrink_to_fit(self: std::pin::Pin<&mut Self>) {
2921 let this = unsafe { self.get_unchecked_mut() };
2922 this.inner.shrink_to_fit();
2923 debug_assert!(this.inner.is_auto_array());
2924 }
2925}
2926
2927// NOTE(emilio): DerefMut wouldn't be safe, see the comment in as_mut_ptr.
2928#[cfg(feature = "gecko-ffi")]
2929impl<T, const N: usize> Deref for AutoThinVec<T, N> {
2930 type Target = ThinVec<T>;
2931
2932 fn deref(&self) -> &Self::Target {
2933 &self.inner
2934 }
2935}
2936
2937/// Create a ThinVec<$ty> named `$name`, with capacity for `$cap` inline elements.
2938///
2939/// TODO(emilio): This would be a lot more convenient to use with super let, see
2940/// <https://github.com/rust-lang/rust/issues/139076>
2941#[cfg(feature = "gecko-ffi")]
2942#[macro_export]
2943macro_rules! auto_thin_vec {
2944 (let $name:ident : [$ty:ty; $cap:literal]) => {
2945 let auto_vec = $crate::AutoThinVec::<$ty, $cap>::new_unpinned();
2946 let mut $name = core::pin::pin!(auto_vec);
2947 unsafe { $name.as_mut().shrink_to_fit_known_singleton() };
2948 };
2949}
2950
2951/// Private helper methods for `Splice::drop`
2952impl<T> Drain<'_, T> {
2953 /// The range from `self.vec.len` to `self.tail_start` contains elements
2954 /// that have been moved out.
2955 /// Fill that range as much as possible with new elements from the `replace_with` iterator.
2956 /// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.)
2957 unsafe fn fill<I: Iterator<Item = T>>(&mut self, replace_with: &mut I) -> bool {
2958 let vec = unsafe { self.vec.as_mut() };
2959 let range_start = vec.len();
2960 let range_end = self.end;
2961 let range_slice = unsafe {
2962 slice::from_raw_parts_mut(vec.data_raw().add(range_start), range_end - range_start)
2963 };
2964
2965 for place in range_slice {
2966 if let Some(new_item) = replace_with.next() {
2967 unsafe { ptr::write(place, new_item) };
2968 vec.set_len(vec.len() + 1);
2969 } else {
2970 return false;
2971 }
2972 }
2973 true
2974 }
2975
2976 /// Makes room for inserting more elements before the tail.
2977 unsafe fn move_tail(&mut self, additional: usize) {
2978 let vec = unsafe { self.vec.as_mut() };
2979 let len = self.end + self.tail;
2980 vec.reserve(len.checked_add(additional).unwrap_cap_overflow());
2981
2982 let new_tail_start = self.end + additional;
2983 unsafe {
2984 let src = vec.data_raw().add(self.end);
2985 let dst = vec.data_raw().add(new_tail_start);
2986 ptr::copy(src, dst, self.tail);
2987 }
2988 self.end = new_tail_start;
2989 }
2990}
2991
2992/// An iterator for [`ThinVec`] which uses a closure to determine if an element should be removed.
2993#[must_use = "iterators are lazy and do nothing unless consumed"]
2994pub struct ExtractIf<'a, T, F> {
2995 vec: &'a mut ThinVec<T>,
2996 /// The index of the item that will be inspected by the next call to `next`.
2997 idx: usize,
2998 /// Elements at and beyond this point will be retained. Must be equal or smaller than `old_len`.
2999 end: usize,
3000 /// The number of items that have been drained (removed) thus far.
3001 del: usize,
3002 /// The original length of `vec` prior to draining.
3003 old_len: usize,
3004 /// The filter test predicate.
3005 pred: F,
3006}
3007
3008impl<T, F> Iterator for ExtractIf<'_, T, F>
3009where
3010 F: FnMut(&mut T) -> bool,
3011{
3012 type Item = T;
3013
3014 fn next(&mut self) -> Option<T> {
3015 unsafe {
3016 let v = self.vec.data_raw();
3017 while self.idx < self.end {
3018 let i = self.idx;
3019 let drained = (self.pred)(&mut *v.add(i));
3020 // Update the index *after* the predicate is called. If the index
3021 // is updated prior and the predicate panics, the element at this
3022 // index would be leaked.
3023 self.idx += 1;
3024 if drained {
3025 self.del += 1;
3026 return Some(ptr::read(v.add(i)));
3027 } else if self.del > 0 {
3028 let del = self.del;
3029 let src: *const T = v.add(i);
3030 let dst: *mut T = v.add(i - del);
3031 ptr::copy_nonoverlapping(src, dst, 1);
3032 }
3033 }
3034 None
3035 }
3036 }
3037
3038 fn size_hint(&self) -> (usize, Option<usize>) {
3039 (0, Some(self.end - self.idx))
3040 }
3041}
3042
3043impl<A, F> Drop for ExtractIf<'_, A, F> {
3044 fn drop(&mut self) {
3045 unsafe {
3046 if self.idx < self.old_len && self.del > 0 {
3047 // This is a pretty messed up state, and there isn't really an
3048 // obviously right thing to do. We don't want to keep trying
3049 // to execute `pred`, so we just backshift all the unprocessed
3050 // elements and tell the vec that they still exist. The backshift
3051 // is required to prevent a double-drop of the last successfully
3052 // drained item prior to a panic in the predicate.
3053 let ptr = self.vec.data_raw();
3054 let src = ptr.add(self.idx);
3055 let dst = src.sub(self.del);
3056 let tail_len = self.old_len - self.idx;
3057 src.copy_to(dst, tail_len);
3058 }
3059
3060 self.vec.set_len(self.old_len - self.del);
3061 }
3062 }
3063}
3064
3065/// Write is implemented for `ThinVec<u8>` by appending to the vector.
3066/// The vector will grow as needed.
3067/// This implementation is identical to the one for `Vec<u8>`.
3068#[cfg(feature = "std")]
3069impl std::io::Write for ThinVec<u8> {
3070 #[inline]
3071 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
3072 self.extend_from_slice(buf);
3073 Ok(buf.len())
3074 }
3075
3076 #[inline]
3077 fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
3078 self.extend_from_slice(buf);
3079 Ok(())
3080 }
3081
3082 #[inline]
3083 fn flush(&mut self) -> std::io::Result<()> {
3084 Ok(())
3085 }
3086}
3087
3088// TODO: a million Index impls
3089
3090#[cfg(test)]
3091mod tests {
3092 use super::{ThinVec, MAX_CAP};
3093 use crate::alloc::{string::ToString, vec};
3094
3095 #[test]
3096 fn test_size_of() {
3097 use core::mem::size_of;
3098 assert_eq!(size_of::<ThinVec<u8>>(), size_of::<&u8>());
3099
3100 assert_eq!(size_of::<Option<ThinVec<u8>>>(), size_of::<&u8>());
3101 }
3102
3103 #[test]
3104 fn test_drop_empty() {
3105 ThinVec::<u8>::new();
3106 }
3107
3108 #[test]
3109 fn test_data_ptr_alignment() {
3110 let v = ThinVec::<u16>::new();
3111 assert!(v.data_raw() as usize % core::mem::align_of::<u16>() == 0);
3112
3113 let v = ThinVec::<u32>::new();
3114 assert!(v.data_raw() as usize % core::mem::align_of::<u32>() == 0);
3115
3116 let v = ThinVec::<u64>::new();
3117 assert!(v.data_raw() as usize % core::mem::align_of::<u64>() == 0);
3118 }
3119
3120 #[test]
3121 #[cfg_attr(feature = "gecko-ffi", should_panic)]
3122 fn test_overaligned_type_is_rejected_for_gecko_ffi_mode() {
3123 #[repr(align(16))]
3124 #[allow(unused)]
3125 struct Align16(u8);
3126
3127 let v = ThinVec::<Align16>::new();
3128 assert!(v.data_raw() as usize % 16 == 0);
3129 }
3130
3131 #[test]
3132 fn test_partial_eq() {
3133 assert_eq!(thin_vec![0], thin_vec![0]);
3134 assert_ne!(thin_vec![0], thin_vec![1]);
3135 assert_eq!(thin_vec![1, 2, 3], vec![1, 2, 3]);
3136 }
3137
3138 #[test]
3139 fn test_alloc() {
3140 let mut v = ThinVec::new();
3141 assert!(!v.has_allocation());
3142 v.push(1);
3143 assert!(v.has_allocation());
3144 v.pop();
3145 assert!(v.has_allocation());
3146 v.shrink_to_fit();
3147 assert!(!v.has_allocation());
3148 v.reserve(64);
3149 assert!(v.has_allocation());
3150 v = ThinVec::with_capacity(64);
3151 assert!(v.has_allocation());
3152 v = ThinVec::with_capacity(0);
3153 assert!(!v.has_allocation());
3154 }
3155
3156 #[test]
3157 fn test_drain_items() {
3158 let mut vec = thin_vec![1, 2, 3];
3159 let mut vec2 = thin_vec![];
3160 for i in vec.drain(..) {
3161 vec2.push(i);
3162 }
3163 assert_eq!(vec, []);
3164 assert_eq!(vec2, [1, 2, 3]);
3165 }
3166
3167 #[test]
3168 fn test_drain_items_reverse() {
3169 let mut vec = thin_vec![1, 2, 3];
3170 let mut vec2 = thin_vec![];
3171 for i in vec.drain(..).rev() {
3172 vec2.push(i);
3173 }
3174 assert_eq!(vec, []);
3175 assert_eq!(vec2, [3, 2, 1]);
3176 }
3177
3178 #[test]
3179 fn test_drain_items_zero_sized() {
3180 let mut vec = thin_vec![(), (), ()];
3181 let mut vec2 = thin_vec![];
3182 for i in vec.drain(..) {
3183 vec2.push(i);
3184 }
3185 assert_eq!(vec, []);
3186 assert_eq!(vec2, [(), (), ()]);
3187 }
3188
3189 #[test]
3190 #[should_panic]
3191 fn test_drain_out_of_bounds() {
3192 let mut v = thin_vec![1, 2, 3, 4, 5];
3193 v.drain(5..6);
3194 }
3195
3196 #[test]
3197 fn test_drain_range() {
3198 let mut v = thin_vec![1, 2, 3, 4, 5];
3199 for _ in v.drain(4..) {}
3200 assert_eq!(v, &[1, 2, 3, 4]);
3201
3202 let mut v: ThinVec<_> = (1..6).map(|x| x.to_string()).collect();
3203 for _ in v.drain(1..4) {}
3204 assert_eq!(v, &[1.to_string(), 5.to_string()]);
3205
3206 let mut v: ThinVec<_> = (1..6).map(|x| x.to_string()).collect();
3207 for _ in v.drain(1..4).rev() {}
3208 assert_eq!(v, &[1.to_string(), 5.to_string()]);
3209
3210 let mut v: ThinVec<_> = thin_vec![(); 5];
3211 for _ in v.drain(1..4).rev() {}
3212 assert_eq!(v, &[(), ()]);
3213 }
3214
3215 #[test]
3216 fn test_drain_max_vec_size() {
3217 let mut v = ThinVec::<()>::with_capacity(MAX_CAP);
3218 unsafe {
3219 v.set_len(MAX_CAP);
3220 }
3221 for _ in v.drain(MAX_CAP - 1..) {}
3222 assert_eq!(v.len(), MAX_CAP - 1);
3223 }
3224
3225 #[test]
3226 fn test_clear() {
3227 let mut v = ThinVec::<i32>::new();
3228 assert_eq!(v.len(), 0);
3229 assert_eq!(v.capacity(), 0);
3230 assert_eq!(&v[..], &[]);
3231
3232 v.clear();
3233 assert_eq!(v.len(), 0);
3234 assert_eq!(v.capacity(), 0);
3235 assert_eq!(&v[..], &[]);
3236
3237 v.push(1);
3238 v.push(2);
3239 assert_eq!(v.len(), 2);
3240 assert!(v.capacity() >= 2);
3241 assert_eq!(&v[..], &[1, 2]);
3242
3243 v.clear();
3244 assert_eq!(v.len(), 0);
3245 assert!(v.capacity() >= 2);
3246 assert_eq!(&v[..], &[]);
3247
3248 v.push(3);
3249 v.push(4);
3250 assert_eq!(v.len(), 2);
3251 assert!(v.capacity() >= 2);
3252 assert_eq!(&v[..], &[3, 4]);
3253
3254 v.clear();
3255 assert_eq!(v.len(), 0);
3256 assert!(v.capacity() >= 2);
3257 assert_eq!(&v[..], &[]);
3258
3259 v.clear();
3260 assert_eq!(v.len(), 0);
3261 assert!(v.capacity() >= 2);
3262 assert_eq!(&v[..], &[]);
3263 }
3264
3265 #[test]
3266 fn test_empty_singleton_torture() {
3267 {
3268 let mut v = ThinVec::<i32>::new();
3269 assert_eq!(v.len(), 0);
3270 assert_eq!(v.capacity(), 0);
3271 assert!(v.is_empty());
3272 assert_eq!(&v[..], &[]);
3273 assert_eq!(&mut v[..], &mut []);
3274
3275 assert_eq!(v.pop(), None);
3276 assert_eq!(v.len(), 0);
3277 assert_eq!(v.capacity(), 0);
3278 assert_eq!(&v[..], &[]);
3279 }
3280
3281 {
3282 let v = ThinVec::<i32>::new();
3283 assert_eq!(v.into_iter().count(), 0);
3284
3285 let v = ThinVec::<i32>::new();
3286 #[allow(clippy::never_loop)]
3287 for _ in v.into_iter() {
3288 unreachable!();
3289 }
3290 }
3291
3292 {
3293 let mut v = ThinVec::<i32>::new();
3294 assert_eq!(v.drain(..).len(), 0);
3295
3296 #[allow(clippy::never_loop)]
3297 for _ in v.drain(..) {
3298 unreachable!()
3299 }
3300
3301 assert_eq!(v.len(), 0);
3302 assert_eq!(v.capacity(), 0);
3303 assert_eq!(&v[..], &[]);
3304 }
3305
3306 {
3307 let mut v = ThinVec::<i32>::new();
3308 assert_eq!(v.splice(.., []).len(), 0);
3309
3310 #[allow(clippy::never_loop)]
3311 for _ in v.splice(.., []) {
3312 unreachable!()
3313 }
3314
3315 assert_eq!(v.len(), 0);
3316 assert_eq!(v.capacity(), 0);
3317 assert_eq!(&v[..], &[]);
3318 }
3319
3320 {
3321 let mut v = ThinVec::<i32>::new();
3322 v.truncate(1);
3323 assert_eq!(v.len(), 0);
3324 assert_eq!(v.capacity(), 0);
3325 assert_eq!(&v[..], &[]);
3326
3327 v.truncate(0);
3328 assert_eq!(v.len(), 0);
3329 assert_eq!(v.capacity(), 0);
3330 assert_eq!(&v[..], &[]);
3331 }
3332
3333 {
3334 let mut v = ThinVec::<i32>::new();
3335 v.shrink_to_fit();
3336 assert_eq!(v.len(), 0);
3337 assert_eq!(v.capacity(), 0);
3338 assert_eq!(&v[..], &[]);
3339 }
3340
3341 {
3342 let mut v = ThinVec::<i32>::new();
3343 let new = v.split_off(0);
3344 assert_eq!(v.len(), 0);
3345 assert_eq!(v.capacity(), 0);
3346 assert_eq!(&v[..], &[]);
3347
3348 assert_eq!(new.len(), 0);
3349 assert_eq!(new.capacity(), 0);
3350 assert_eq!(&new[..], &[]);
3351 }
3352
3353 {
3354 let mut v = ThinVec::<i32>::new();
3355 let mut other = ThinVec::<i32>::new();
3356 v.append(&mut other);
3357
3358 assert_eq!(v.len(), 0);
3359 assert_eq!(v.capacity(), 0);
3360 assert_eq!(&v[..], &[]);
3361
3362 assert_eq!(other.len(), 0);
3363 assert_eq!(other.capacity(), 0);
3364 assert_eq!(&other[..], &[]);
3365 }
3366
3367 {
3368 let mut v = ThinVec::<i32>::new();
3369 v.reserve(0);
3370
3371 assert_eq!(v.len(), 0);
3372 assert_eq!(v.capacity(), 0);
3373 assert_eq!(&v[..], &[]);
3374 }
3375
3376 {
3377 let mut v = ThinVec::<i32>::new();
3378 v.reserve_exact(0);
3379
3380 assert_eq!(v.len(), 0);
3381 assert_eq!(v.capacity(), 0);
3382 assert_eq!(&v[..], &[]);
3383 }
3384
3385 {
3386 let mut v = ThinVec::<i32>::new();
3387 v.reserve(0);
3388
3389 assert_eq!(v.len(), 0);
3390 assert_eq!(v.capacity(), 0);
3391 assert_eq!(&v[..], &[]);
3392 }
3393
3394 {
3395 let v = ThinVec::<i32>::with_capacity(0);
3396
3397 assert_eq!(v.len(), 0);
3398 assert_eq!(v.capacity(), 0);
3399 assert_eq!(&v[..], &[]);
3400 }
3401
3402 {
3403 let v = ThinVec::<i32>::default();
3404
3405 assert_eq!(v.len(), 0);
3406 assert_eq!(v.capacity(), 0);
3407 assert_eq!(&v[..], &[]);
3408 }
3409
3410 {
3411 let mut v = ThinVec::<i32>::new();
3412 v.retain(|_| unreachable!());
3413
3414 assert_eq!(v.len(), 0);
3415 assert_eq!(v.capacity(), 0);
3416 assert_eq!(&v[..], &[]);
3417 }
3418
3419 {
3420 let mut v = ThinVec::<i32>::new();
3421 v.retain_mut(|_| unreachable!());
3422
3423 assert_eq!(v.len(), 0);
3424 assert_eq!(v.capacity(), 0);
3425 assert_eq!(&v[..], &[]);
3426 }
3427
3428 {
3429 let mut v = ThinVec::<i32>::new();
3430 v.dedup_by_key(|x| *x);
3431
3432 assert_eq!(v.len(), 0);
3433 assert_eq!(v.capacity(), 0);
3434 assert_eq!(&v[..], &[]);
3435 }
3436
3437 {
3438 let mut v = ThinVec::<i32>::new();
3439 v.dedup_by(|_, _| unreachable!());
3440
3441 assert_eq!(v.len(), 0);
3442 assert_eq!(v.capacity(), 0);
3443 assert_eq!(&v[..], &[]);
3444 }
3445
3446 {
3447 let v = ThinVec::<i32>::new();
3448 let v = v.clone();
3449
3450 assert_eq!(v.len(), 0);
3451 assert_eq!(v.capacity(), 0);
3452 assert_eq!(&v[..], &[]);
3453 }
3454 }
3455
3456 #[test]
3457 fn test_clone() {
3458 let mut v = ThinVec::<i32>::new();
3459 assert!(v.is_singleton());
3460 v.push(0);
3461 v.pop();
3462 assert!(!v.is_singleton());
3463
3464 let v2 = v.clone();
3465 assert!(v2.is_singleton());
3466 }
3467}
3468
3469#[cfg(test)]
3470mod std_tests {
3471 #![allow(clippy::reversed_empty_ranges)]
3472
3473 use super::*;
3474 use crate::alloc::{
3475 format,
3476 string::{String, ToString},
3477 };
3478 use core::mem::size_of;
3479
3480 struct DropCounter<'a> {
3481 count: &'a mut u32,
3482 }
3483
3484 impl<'a> Drop for DropCounter<'a> {
3485 fn drop(&mut self) {
3486 *self.count += 1;
3487 }
3488 }
3489
3490 #[test]
3491 fn test_small_vec_struct() {
3492 assert!(size_of::<ThinVec<u8>>() == size_of::<usize>());
3493 }
3494
3495 #[test]
3496 fn test_double_drop() {
3497 struct TwoVec<T> {
3498 x: ThinVec<T>,
3499 y: ThinVec<T>,
3500 }
3501
3502 let (mut count_x, mut count_y) = (0, 0);
3503 {
3504 let mut tv = TwoVec {
3505 x: ThinVec::new(),
3506 y: ThinVec::new(),
3507 };
3508 tv.x.push(DropCounter {
3509 count: &mut count_x,
3510 });
3511 tv.y.push(DropCounter {
3512 count: &mut count_y,
3513 });
3514
3515 // If ThinVec had a drop flag, here is where it would be zeroed.
3516 // Instead, it should rely on its internal state to prevent
3517 // doing anything significant when dropped multiple times.
3518 drop(tv.x);
3519
3520 // Here tv goes out of scope, tv.y should be dropped, but not tv.x.
3521 }
3522
3523 assert_eq!(count_x, 1);
3524 assert_eq!(count_y, 1);
3525 }
3526
3527 #[test]
3528 fn test_reserve() {
3529 let mut v = ThinVec::new();
3530 assert_eq!(v.capacity(), 0);
3531
3532 v.reserve(2);
3533 assert!(v.capacity() >= 2);
3534
3535 for i in 0..16 {
3536 v.push(i);
3537 }
3538
3539 assert!(v.capacity() >= 16);
3540 v.reserve(16);
3541 assert!(v.capacity() >= 32);
3542
3543 v.push(16);
3544
3545 v.reserve(16);
3546 assert!(v.capacity() >= 33)
3547 }
3548
3549 #[test]
3550 fn test_extend() {
3551 let mut v = ThinVec::<usize>::new();
3552 let mut w = ThinVec::new();
3553 v.extend(w.clone());
3554 assert_eq!(v, &[]);
3555
3556 v.extend(0..3);
3557 for i in 0..3 {
3558 w.push(i)
3559 }
3560
3561 assert_eq!(v, w);
3562
3563 v.extend(3..10);
3564 for i in 3..10 {
3565 w.push(i)
3566 }
3567
3568 assert_eq!(v, w);
3569
3570 v.extend(w.clone()); // specializes to `append`
3571 assert!(v.iter().eq(w.iter().chain(w.iter())));
3572
3573 // Zero sized types
3574 #[derive(PartialEq, Debug)]
3575 struct Foo;
3576
3577 let mut a = ThinVec::new();
3578 let b = thin_vec![Foo, Foo];
3579
3580 a.extend(b);
3581 assert_eq!(a, &[Foo, Foo]);
3582
3583 // Double drop
3584 let mut count_x = 0;
3585 {
3586 let mut x = ThinVec::new();
3587 let y = thin_vec![DropCounter {
3588 count: &mut count_x
3589 }];
3590 x.extend(y);
3591 }
3592
3593 assert_eq!(count_x, 1);
3594 }
3595
3596 /* TODO: implement extend for Iter<&Copy>
3597 #[test]
3598 fn test_extend_ref() {
3599 let mut v = thin_vec![1, 2];
3600 v.extend(&[3, 4, 5]);
3601
3602 assert_eq!(v.len(), 5);
3603 assert_eq!(v, [1, 2, 3, 4, 5]);
3604
3605 let w = thin_vec![6, 7];
3606 v.extend(&w);
3607
3608 assert_eq!(v.len(), 7);
3609 assert_eq!(v, [1, 2, 3, 4, 5, 6, 7]);
3610 }
3611 */
3612
3613 #[test]
3614 fn test_slice_from_mut() {
3615 let mut values = thin_vec![1, 2, 3, 4, 5];
3616 {
3617 let slice = &mut values[2..];
3618 assert!(slice == [3, 4, 5]);
3619 for p in slice {
3620 *p += 2;
3621 }
3622 }
3623
3624 assert!(values == [1, 2, 5, 6, 7]);
3625 }
3626
3627 #[test]
3628 fn test_slice_to_mut() {
3629 let mut values = thin_vec![1, 2, 3, 4, 5];
3630 {
3631 let slice = &mut values[..2];
3632 assert!(slice == [1, 2]);
3633 for p in slice {
3634 *p += 1;
3635 }
3636 }
3637
3638 assert!(values == [2, 3, 3, 4, 5]);
3639 }
3640
3641 #[test]
3642 fn test_split_at_mut() {
3643 let mut values = thin_vec![1, 2, 3, 4, 5];
3644 {
3645 let (left, right) = values.split_at_mut(2);
3646 {
3647 let left: &[_] = left;
3648 assert!(left[..left.len()] == [1, 2]);
3649 }
3650 for p in left {
3651 *p += 1;
3652 }
3653
3654 {
3655 let right: &[_] = right;
3656 assert!(right[..right.len()] == [3, 4, 5]);
3657 }
3658 for p in right {
3659 *p += 2;
3660 }
3661 }
3662
3663 assert_eq!(values, [2, 3, 5, 6, 7]);
3664 }
3665
3666 #[test]
3667 fn test_clone() {
3668 let v: ThinVec<i32> = thin_vec![];
3669 let w = thin_vec![1, 2, 3];
3670
3671 assert_eq!(v, v.clone());
3672
3673 let z = w.clone();
3674 assert_eq!(w, z);
3675 // they should be disjoint in memory.
3676 assert!(w.as_ptr() != z.as_ptr())
3677 }
3678
3679 #[test]
3680 fn test_clone_from() {
3681 let mut v = thin_vec![];
3682 let three: ThinVec<Box<_>> = thin_vec![Box::new(1), Box::new(2), Box::new(3)];
3683 let two: ThinVec<Box<_>> = thin_vec![Box::new(4), Box::new(5)];
3684 // zero, long
3685 v.clone_from(&three);
3686 assert_eq!(v, three);
3687
3688 // equal
3689 v.clone_from(&three);
3690 assert_eq!(v, three);
3691
3692 // long, short
3693 v.clone_from(&two);
3694 assert_eq!(v, two);
3695
3696 // short, long
3697 v.clone_from(&three);
3698 assert_eq!(v, three)
3699 }
3700
3701 #[test]
3702 fn test_retain() {
3703 let mut vec = thin_vec![1, 2, 3, 4];
3704 vec.retain(|&x| x % 2 == 0);
3705 assert_eq!(vec, [2, 4]);
3706 }
3707
3708 #[test]
3709 fn test_retain_mut() {
3710 let mut vec = thin_vec![9, 9, 9, 9];
3711 let mut i = 0;
3712 vec.retain_mut(|x| {
3713 i += 1;
3714 *x = i;
3715 i != 4
3716 });
3717 assert_eq!(vec, [1, 2, 3]);
3718 }
3719
3720 #[test]
3721 fn test_dedup() {
3722 fn case(a: ThinVec<i32>, b: ThinVec<i32>) {
3723 let mut v = a;
3724 v.dedup();
3725 assert_eq!(v, b);
3726 }
3727 case(thin_vec![], thin_vec![]);
3728 case(thin_vec![1], thin_vec![1]);
3729 case(thin_vec![1, 1], thin_vec![1]);
3730 case(thin_vec![1, 2, 3], thin_vec![1, 2, 3]);
3731 case(thin_vec![1, 1, 2, 3], thin_vec![1, 2, 3]);
3732 case(thin_vec![1, 2, 2, 3], thin_vec![1, 2, 3]);
3733 case(thin_vec![1, 2, 3, 3], thin_vec![1, 2, 3]);
3734 case(thin_vec![1, 1, 2, 2, 2, 3, 3], thin_vec![1, 2, 3]);
3735 }
3736
3737 #[test]
3738 fn test_dedup_by_key() {
3739 fn case(a: ThinVec<i32>, b: ThinVec<i32>) {
3740 let mut v = a;
3741 v.dedup_by_key(|i| *i / 10);
3742 assert_eq!(v, b);
3743 }
3744 case(thin_vec![], thin_vec![]);
3745 case(thin_vec![10], thin_vec![10]);
3746 case(thin_vec![10, 11], thin_vec![10]);
3747 case(thin_vec![10, 20, 30], thin_vec![10, 20, 30]);
3748 case(thin_vec![10, 11, 20, 30], thin_vec![10, 20, 30]);
3749 case(thin_vec![10, 20, 21, 30], thin_vec![10, 20, 30]);
3750 case(thin_vec![10, 20, 30, 31], thin_vec![10, 20, 30]);
3751 case(thin_vec![10, 11, 20, 21, 22, 30, 31], thin_vec![10, 20, 30]);
3752 }
3753
3754 #[test]
3755 fn test_dedup_by() {
3756 let mut vec = thin_vec!["foo", "bar", "Bar", "baz", "bar"];
3757 vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
3758
3759 assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
3760
3761 let mut vec = thin_vec![("foo", 1), ("foo", 2), ("bar", 3), ("bar", 4), ("bar", 5)];
3762 vec.dedup_by(|a, b| {
3763 a.0 == b.0 && {
3764 b.1 += a.1;
3765 true
3766 }
3767 });
3768
3769 assert_eq!(vec, [("foo", 3), ("bar", 12)]);
3770 }
3771
3772 #[test]
3773 fn test_dedup_unique() {
3774 let mut v0: ThinVec<Box<_>> = thin_vec![Box::new(1), Box::new(1), Box::new(2), Box::new(3)];
3775 v0.dedup();
3776 let mut v1: ThinVec<Box<_>> = thin_vec![Box::new(1), Box::new(2), Box::new(2), Box::new(3)];
3777 v1.dedup();
3778 let mut v2: ThinVec<Box<_>> = thin_vec![Box::new(1), Box::new(2), Box::new(3), Box::new(3)];
3779 v2.dedup();
3780 // If the boxed pointers were leaked or otherwise misused, valgrind
3781 // and/or rt should raise errors.
3782 }
3783
3784 #[test]
3785 fn zero_sized_values() {
3786 let mut v = ThinVec::new();
3787 assert_eq!(v.len(), 0);
3788 v.push(());
3789 assert_eq!(v.len(), 1);
3790 v.push(());
3791 assert_eq!(v.len(), 2);
3792 assert_eq!(v.pop(), Some(()));
3793 assert_eq!(v.pop(), Some(()));
3794 assert_eq!(v.pop(), None);
3795
3796 assert_eq!(v.iter().count(), 0);
3797 v.push(());
3798 assert_eq!(v.iter().count(), 1);
3799 v.push(());
3800 assert_eq!(v.iter().count(), 2);
3801
3802 for &() in &v {}
3803
3804 assert_eq!(v.iter_mut().count(), 2);
3805 v.push(());
3806 assert_eq!(v.iter_mut().count(), 3);
3807 v.push(());
3808 assert_eq!(v.iter_mut().count(), 4);
3809
3810 for &mut () in &mut v {}
3811 unsafe {
3812 v.set_len(0);
3813 }
3814 assert_eq!(v.iter_mut().count(), 0);
3815 }
3816
3817 #[test]
3818 fn test_partition() {
3819 assert_eq!(
3820 thin_vec![].into_iter().partition(|x: &i32| *x < 3),
3821 (thin_vec![], thin_vec![])
3822 );
3823 assert_eq!(
3824 thin_vec![1, 2, 3].into_iter().partition(|x| *x < 4),
3825 (thin_vec![1, 2, 3], thin_vec![])
3826 );
3827 assert_eq!(
3828 thin_vec![1, 2, 3].into_iter().partition(|x| *x < 2),
3829 (thin_vec![1], thin_vec![2, 3])
3830 );
3831 assert_eq!(
3832 thin_vec![1, 2, 3].into_iter().partition(|x| *x < 0),
3833 (thin_vec![], thin_vec![1, 2, 3])
3834 );
3835 }
3836
3837 #[test]
3838 fn test_zip_unzip() {
3839 let z1 = thin_vec![(1, 4), (2, 5), (3, 6)];
3840
3841 let (left, right): (ThinVec<_>, ThinVec<_>) = z1.iter().cloned().unzip();
3842
3843 assert_eq!((1, 4), (left[0], right[0]));
3844 assert_eq!((2, 5), (left[1], right[1]));
3845 assert_eq!((3, 6), (left[2], right[2]));
3846 }
3847
3848 #[test]
3849 fn test_vec_truncate_drop() {
3850 static mut DROPS: u32 = 0;
3851 #[allow(unused)]
3852 struct Elem(i32);
3853 impl Drop for Elem {
3854 fn drop(&mut self) {
3855 unsafe {
3856 DROPS += 1;
3857 }
3858 }
3859 }
3860
3861 let mut v = thin_vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)];
3862 assert_eq!(unsafe { DROPS }, 0);
3863 v.truncate(3);
3864 assert_eq!(unsafe { DROPS }, 2);
3865 v.truncate(0);
3866 assert_eq!(unsafe { DROPS }, 5);
3867 }
3868
3869 #[test]
3870 #[should_panic]
3871 fn test_vec_truncate_fail() {
3872 struct BadElem(i32);
3873 impl Drop for BadElem {
3874 fn drop(&mut self) {
3875 let BadElem(ref mut x) = *self;
3876 if *x == 0xbadbeef {
3877 panic!("BadElem panic: 0xbadbeef")
3878 }
3879 }
3880 }
3881
3882 let mut v = thin_vec![BadElem(1), BadElem(2), BadElem(0xbadbeef), BadElem(4)];
3883 v.truncate(0);
3884 }
3885
3886 #[test]
3887 fn test_index() {
3888 let vec = thin_vec![1, 2, 3];
3889 assert!(vec[1] == 2);
3890 }
3891
3892 #[test]
3893 #[should_panic]
3894 fn test_index_out_of_bounds() {
3895 let vec = thin_vec![1, 2, 3];
3896 let _ = vec[3];
3897 }
3898
3899 #[test]
3900 #[should_panic]
3901 fn test_slice_out_of_bounds_1() {
3902 let x = thin_vec![1, 2, 3, 4, 5];
3903 let _ = &x[!0..];
3904 }
3905
3906 #[test]
3907 #[should_panic]
3908 fn test_slice_out_of_bounds_2() {
3909 let x = thin_vec![1, 2, 3, 4, 5];
3910 let _ = &x[..6];
3911 }
3912
3913 #[test]
3914 #[should_panic]
3915 fn test_slice_out_of_bounds_3() {
3916 let x = thin_vec![1, 2, 3, 4, 5];
3917 let _ = &x[!0..4];
3918 }
3919
3920 #[test]
3921 #[should_panic]
3922 fn test_slice_out_of_bounds_4() {
3923 let x = thin_vec![1, 2, 3, 4, 5];
3924 let _ = &x[1..6];
3925 }
3926
3927 #[test]
3928 #[should_panic]
3929 fn test_slice_out_of_bounds_5() {
3930 let x = thin_vec![1, 2, 3, 4, 5];
3931 let _ = &x[3..2];
3932 }
3933
3934 #[test]
3935 #[should_panic]
3936 fn test_swap_remove_empty() {
3937 let mut vec = ThinVec::<i32>::new();
3938 vec.swap_remove(0);
3939 }
3940
3941 #[test]
3942 fn test_move_items() {
3943 let vec = thin_vec![1, 2, 3];
3944 let mut vec2 = thin_vec![];
3945 for i in vec {
3946 vec2.push(i);
3947 }
3948 assert_eq!(vec2, [1, 2, 3]);
3949 }
3950
3951 #[test]
3952 fn test_move_items_reverse() {
3953 let vec = thin_vec![1, 2, 3];
3954 let mut vec2 = thin_vec![];
3955 for i in vec.into_iter().rev() {
3956 vec2.push(i);
3957 }
3958 assert_eq!(vec2, [3, 2, 1]);
3959 }
3960
3961 #[test]
3962 fn test_move_items_zero_sized() {
3963 let vec = thin_vec![(), (), ()];
3964 let mut vec2 = thin_vec![];
3965 for i in vec {
3966 vec2.push(i);
3967 }
3968 assert_eq!(vec2, [(), (), ()]);
3969 }
3970
3971 #[test]
3972 fn test_drain_items() {
3973 let mut vec = thin_vec![1, 2, 3];
3974 let mut vec2 = thin_vec![];
3975 for i in vec.drain(..) {
3976 vec2.push(i);
3977 }
3978 assert_eq!(vec, []);
3979 assert_eq!(vec2, [1, 2, 3]);
3980 }
3981
3982 #[test]
3983 fn test_drain_items_reverse() {
3984 let mut vec = thin_vec![1, 2, 3];
3985 let mut vec2 = thin_vec![];
3986 for i in vec.drain(..).rev() {
3987 vec2.push(i);
3988 }
3989 assert_eq!(vec, []);
3990 assert_eq!(vec2, [3, 2, 1]);
3991 }
3992
3993 #[test]
3994 fn test_drain_items_zero_sized() {
3995 let mut vec = thin_vec![(), (), ()];
3996 let mut vec2 = thin_vec![];
3997 for i in vec.drain(..) {
3998 vec2.push(i);
3999 }
4000 assert_eq!(vec, []);
4001 assert_eq!(vec2, [(), (), ()]);
4002 }
4003
4004 #[test]
4005 #[should_panic]
4006 fn test_drain_out_of_bounds() {
4007 let mut v = thin_vec![1, 2, 3, 4, 5];
4008 v.drain(5..6);
4009 }
4010
4011 #[test]
4012 fn test_drain_range() {
4013 let mut v = thin_vec![1, 2, 3, 4, 5];
4014 for _ in v.drain(4..) {}
4015 assert_eq!(v, &[1, 2, 3, 4]);
4016
4017 let mut v: ThinVec<_> = (1..6).map(|x| x.to_string()).collect();
4018 for _ in v.drain(1..4) {}
4019 assert_eq!(v, &[1.to_string(), 5.to_string()]);
4020
4021 let mut v: ThinVec<_> = (1..6).map(|x| x.to_string()).collect();
4022 for _ in v.drain(1..4).rev() {}
4023 assert_eq!(v, &[1.to_string(), 5.to_string()]);
4024
4025 let mut v: ThinVec<_> = thin_vec![(); 5];
4026 for _ in v.drain(1..4).rev() {}
4027 assert_eq!(v, &[(), ()]);
4028 }
4029
4030 #[test]
4031 fn test_drain_inclusive_range() {
4032 let mut v = thin_vec!['a', 'b', 'c', 'd', 'e'];
4033 for _ in v.drain(1..=3) {}
4034 assert_eq!(v, &['a', 'e']);
4035
4036 let mut v: ThinVec<_> = (0..=5).map(|x| x.to_string()).collect();
4037 for _ in v.drain(1..=5) {}
4038 assert_eq!(v, &["0".to_string()]);
4039
4040 let mut v: ThinVec<String> = (0..=5).map(|x| x.to_string()).collect();
4041 for _ in v.drain(0..=5) {}
4042 assert_eq!(v, ThinVec::<String>::new());
4043
4044 let mut v: ThinVec<_> = (0..=5).map(|x| x.to_string()).collect();
4045 for _ in v.drain(0..=3) {}
4046 assert_eq!(v, &["4".to_string(), "5".to_string()]);
4047
4048 let mut v: ThinVec<_> = (0..=1).map(|x| x.to_string()).collect();
4049 for _ in v.drain(..=0) {}
4050 assert_eq!(v, &["1".to_string()]);
4051 }
4052
4053 #[test]
4054 #[cfg(not(feature = "gecko-ffi"))]
4055 fn test_drain_max_vec_size() {
4056 let mut v = ThinVec::<()>::with_capacity(usize::MAX);
4057 unsafe {
4058 v.set_len(usize::MAX);
4059 }
4060 for _ in v.drain(usize::MAX - 1..) {}
4061 assert_eq!(v.len(), usize::MAX - 1);
4062
4063 let mut v = ThinVec::<()>::with_capacity(usize::MAX);
4064 unsafe {
4065 v.set_len(usize::MAX);
4066 }
4067 for _ in v.drain(usize::MAX - 1..=usize::MAX - 1) {}
4068 assert_eq!(v.len(), usize::MAX - 1);
4069 }
4070
4071 #[test]
4072 #[should_panic]
4073 fn test_drain_inclusive_out_of_bounds() {
4074 let mut v = thin_vec![1, 2, 3, 4, 5];
4075 v.drain(5..=5);
4076 }
4077
4078 #[test]
4079 fn test_splice() {
4080 let mut v = thin_vec![1, 2, 3, 4, 5];
4081 let a = [10, 11, 12];
4082 v.splice(2..4, a.iter().cloned());
4083 assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
4084 v.splice(1..3, Some(20));
4085 assert_eq!(v, &[1, 20, 11, 12, 5]);
4086 }
4087
4088 #[test]
4089 fn test_splice_inclusive_range() {
4090 let mut v = thin_vec![1, 2, 3, 4, 5];
4091 let a = [10, 11, 12];
4092 let t1: ThinVec<_> = v.splice(2..=3, a.iter().cloned()).collect();
4093 assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
4094 assert_eq!(t1, &[3, 4]);
4095 let t2: ThinVec<_> = v.splice(1..=2, Some(20)).collect();
4096 assert_eq!(v, &[1, 20, 11, 12, 5]);
4097 assert_eq!(t2, &[2, 10]);
4098 }
4099
4100 #[test]
4101 #[should_panic]
4102 fn test_splice_out_of_bounds() {
4103 let mut v = thin_vec![1, 2, 3, 4, 5];
4104 let a = [10, 11, 12];
4105 v.splice(5..6, a.iter().cloned());
4106 }
4107
4108 #[test]
4109 #[should_panic]
4110 fn test_splice_inclusive_out_of_bounds() {
4111 let mut v = thin_vec![1, 2, 3, 4, 5];
4112 let a = [10, 11, 12];
4113 v.splice(5..=5, a.iter().cloned());
4114 }
4115
4116 #[test]
4117 fn test_splice_items_zero_sized() {
4118 let mut vec = thin_vec![(), (), ()];
4119 let vec2 = thin_vec![];
4120 let t: ThinVec<_> = vec.splice(1..2, vec2.iter().cloned()).collect();
4121 assert_eq!(vec, &[(), ()]);
4122 assert_eq!(t, &[()]);
4123 }
4124
4125 #[test]
4126 fn test_splice_unbounded() {
4127 let mut vec = thin_vec![1, 2, 3, 4, 5];
4128 let t: ThinVec<_> = vec.splice(.., None).collect();
4129 assert_eq!(vec, &[]);
4130 assert_eq!(t, &[1, 2, 3, 4, 5]);
4131 }
4132
4133 #[test]
4134 fn test_splice_forget() {
4135 let mut v = thin_vec![1, 2, 3, 4, 5];
4136 let a = [10, 11, 12];
4137 ::core::mem::forget(v.splice(2..4, a.iter().cloned()));
4138 assert_eq!(v, &[1, 2]);
4139 }
4140
4141 #[test]
4142 fn test_splice_from_empty() {
4143 let mut v = thin_vec![];
4144 let a = [10, 11, 12];
4145 v.splice(.., a.iter().cloned());
4146 assert_eq!(v, &[10, 11, 12]);
4147 }
4148
4149 /* probs won't ever impl this
4150 #[test]
4151 fn test_into_boxed_slice() {
4152 let xs = thin_vec![1, 2, 3];
4153 let ys = xs.into_boxed_slice();
4154 assert_eq!(&*ys, [1, 2, 3]);
4155 }
4156 */
4157
4158 #[test]
4159 fn test_append() {
4160 let mut vec = thin_vec![1, 2, 3];
4161 let mut vec2 = thin_vec![4, 5, 6];
4162 vec.append(&mut vec2);
4163 assert_eq!(vec, [1, 2, 3, 4, 5, 6]);
4164 assert_eq!(vec2, []);
4165 }
4166
4167 #[test]
4168 fn test_split_off() {
4169 let mut vec = thin_vec![1, 2, 3, 4, 5, 6];
4170 let vec2 = vec.split_off(4);
4171 assert_eq!(vec, [1, 2, 3, 4]);
4172 assert_eq!(vec2, [5, 6]);
4173 }
4174
4175 #[test]
4176 fn test_into_iter_as_slice() {
4177 let vec = thin_vec!['a', 'b', 'c'];
4178 let mut into_iter = vec.into_iter();
4179 assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
4180 let _ = into_iter.next().unwrap();
4181 assert_eq!(into_iter.as_slice(), &['b', 'c']);
4182 let _ = into_iter.next().unwrap();
4183 let _ = into_iter.next().unwrap();
4184 assert_eq!(into_iter.as_slice(), &[]);
4185 }
4186
4187 #[test]
4188 fn test_into_iter_as_mut_slice() {
4189 let vec = thin_vec!['a', 'b', 'c'];
4190 let mut into_iter = vec.into_iter();
4191 assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
4192 into_iter.as_mut_slice()[0] = 'x';
4193 into_iter.as_mut_slice()[1] = 'y';
4194 assert_eq!(into_iter.next().unwrap(), 'x');
4195 assert_eq!(into_iter.as_slice(), &['y', 'c']);
4196 }
4197
4198 #[test]
4199 fn test_into_iter_debug() {
4200 let vec = thin_vec!['a', 'b', 'c'];
4201 let into_iter = vec.into_iter();
4202 let debug = format!("{:?}", into_iter);
4203 assert_eq!(debug, "IntoIter(['a', 'b', 'c'])");
4204 }
4205
4206 #[test]
4207 fn test_into_iter_count() {
4208 assert_eq!(thin_vec![1, 2, 3].into_iter().count(), 3);
4209 }
4210
4211 #[test]
4212 fn test_into_iter_clone() {
4213 fn iter_equal<I: Iterator<Item = i32>>(it: I, slice: &[i32]) {
4214 let v: ThinVec<i32> = it.collect();
4215 assert_eq!(&v[..], slice);
4216 }
4217 let mut it = thin_vec![1, 2, 3].into_iter();
4218 iter_equal(it.clone(), &[1, 2, 3]);
4219 assert_eq!(it.next(), Some(1));
4220 let mut it = it.rev();
4221 iter_equal(it.clone(), &[3, 2]);
4222 assert_eq!(it.next(), Some(3));
4223 iter_equal(it.clone(), &[2]);
4224 assert_eq!(it.next(), Some(2));
4225 iter_equal(it.clone(), &[]);
4226 assert_eq!(it.next(), None);
4227 }
4228
4229 #[allow(dead_code)]
4230 fn assert_covariance() {
4231 fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
4232 d
4233 }
4234 fn into_iter<'new>(i: IntoIter<&'static str>) -> IntoIter<&'new str> {
4235 i
4236 }
4237 }
4238
4239 /* TODO: specialize vec.into_iter().collect::<ThinVec<_>>();
4240 #[test]
4241 fn from_into_inner() {
4242 let vec = thin_vec![1, 2, 3];
4243 let ptr = vec.as_ptr();
4244 let vec = vec.into_iter().collect::<ThinVec<_>>();
4245 assert_eq!(vec, [1, 2, 3]);
4246 assert_eq!(vec.as_ptr(), ptr);
4247
4248 let ptr = &vec[1] as *const _;
4249 let mut it = vec.into_iter();
4250 it.next().unwrap();
4251 let vec = it.collect::<ThinVec<_>>();
4252 assert_eq!(vec, [2, 3]);
4253 assert!(ptr != vec.as_ptr());
4254 }
4255 */
4256
4257 #[test]
4258 #[cfg_attr(feature = "gecko-ffi", ignore)]
4259 fn overaligned_allocations() {
4260 #[repr(align(256))]
4261 struct Foo(usize);
4262 let mut v = thin_vec![Foo(273)];
4263 for i in 0..0x1000 {
4264 v.reserve_exact(i);
4265 assert!(v[0].0 == 273);
4266 assert!(v.as_ptr() as usize & 0xff == 0);
4267 v.shrink_to_fit();
4268 assert!(v[0].0 == 273);
4269 assert!(v.as_ptr() as usize & 0xff == 0);
4270 }
4271 }
4272
4273 /* TODO: implement drain_filter?
4274 #[test]
4275 fn drain_filter_empty() {
4276 let mut vec: ThinVec<i32> = thin_vec![];
4277
4278 {
4279 let mut iter = vec.drain_filter(|_| true);
4280 assert_eq!(iter.size_hint(), (0, Some(0)));
4281 assert_eq!(iter.next(), None);
4282 assert_eq!(iter.size_hint(), (0, Some(0)));
4283 assert_eq!(iter.next(), None);
4284 assert_eq!(iter.size_hint(), (0, Some(0)));
4285 }
4286 assert_eq!(vec.len(), 0);
4287 assert_eq!(vec, thin_vec![]);
4288 }
4289
4290 #[test]
4291 fn drain_filter_zst() {
4292 let mut vec = thin_vec![(), (), (), (), ()];
4293 let initial_len = vec.len();
4294 let mut count = 0;
4295 {
4296 let mut iter = vec.drain_filter(|_| true);
4297 assert_eq!(iter.size_hint(), (0, Some(initial_len)));
4298 while let Some(_) = iter.next() {
4299 count += 1;
4300 assert_eq!(iter.size_hint(), (0, Some(initial_len - count)));
4301 }
4302 assert_eq!(iter.size_hint(), (0, Some(0)));
4303 assert_eq!(iter.next(), None);
4304 assert_eq!(iter.size_hint(), (0, Some(0)));
4305 }
4306
4307 assert_eq!(count, initial_len);
4308 assert_eq!(vec.len(), 0);
4309 assert_eq!(vec, thin_vec![]);
4310 }
4311
4312 #[test]
4313 fn drain_filter_false() {
4314 let mut vec = thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
4315
4316 let initial_len = vec.len();
4317 let mut count = 0;
4318 {
4319 let mut iter = vec.drain_filter(|_| false);
4320 assert_eq!(iter.size_hint(), (0, Some(initial_len)));
4321 for _ in iter.by_ref() {
4322 count += 1;
4323 }
4324 assert_eq!(iter.size_hint(), (0, Some(0)));
4325 assert_eq!(iter.next(), None);
4326 assert_eq!(iter.size_hint(), (0, Some(0)));
4327 }
4328
4329 assert_eq!(count, 0);
4330 assert_eq!(vec.len(), initial_len);
4331 assert_eq!(vec, thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
4332 }
4333
4334 #[test]
4335 fn drain_filter_true() {
4336 let mut vec = thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
4337
4338 let initial_len = vec.len();
4339 let mut count = 0;
4340 {
4341 let mut iter = vec.drain_filter(|_| true);
4342 assert_eq!(iter.size_hint(), (0, Some(initial_len)));
4343 while let Some(_) = iter.next() {
4344 count += 1;
4345 assert_eq!(iter.size_hint(), (0, Some(initial_len - count)));
4346 }
4347 assert_eq!(iter.size_hint(), (0, Some(0)));
4348 assert_eq!(iter.next(), None);
4349 assert_eq!(iter.size_hint(), (0, Some(0)));
4350 }
4351
4352 assert_eq!(count, initial_len);
4353 assert_eq!(vec.len(), 0);
4354 assert_eq!(vec, thin_vec![]);
4355 }
4356
4357 #[test]
4358 fn drain_filter_complex() {
4359
4360 { // [+xxx++++++xxxxx++++x+x++]
4361 let mut vec = thin_vec![1,
4362 2, 4, 6,
4363 7, 9, 11, 13, 15, 17,
4364 18, 20, 22, 24, 26,
4365 27, 29, 31, 33,
4366 34,
4367 35,
4368 36,
4369 37, 39];
4370
4371 let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<ThinVec<_>>();
4372 assert_eq!(removed.len(), 10);
4373 assert_eq!(removed, thin_vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
4374
4375 assert_eq!(vec.len(), 14);
4376 assert_eq!(vec, thin_vec![1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]);
4377 }
4378
4379 { // [xxx++++++xxxxx++++x+x++]
4380 let mut vec = thin_vec![2, 4, 6,
4381 7, 9, 11, 13, 15, 17,
4382 18, 20, 22, 24, 26,
4383 27, 29, 31, 33,
4384 34,
4385 35,
4386 36,
4387 37, 39];
4388
4389 let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<ThinVec<_>>();
4390 assert_eq!(removed.len(), 10);
4391 assert_eq!(removed, thin_vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
4392
4393 assert_eq!(vec.len(), 13);
4394 assert_eq!(vec, thin_vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]);
4395 }
4396
4397 { // [xxx++++++xxxxx++++x+x]
4398 let mut vec = thin_vec![2, 4, 6,
4399 7, 9, 11, 13, 15, 17,
4400 18, 20, 22, 24, 26,
4401 27, 29, 31, 33,
4402 34,
4403 35,
4404 36];
4405
4406 let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<ThinVec<_>>();
4407 assert_eq!(removed.len(), 10);
4408 assert_eq!(removed, thin_vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
4409
4410 assert_eq!(vec.len(), 11);
4411 assert_eq!(vec, thin_vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35]);
4412 }
4413
4414 { // [xxxxxxxxxx+++++++++++]
4415 let mut vec = thin_vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
4416 1, 3, 5, 7, 9, 11, 13, 15, 17, 19];
4417
4418 let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<ThinVec<_>>();
4419 assert_eq!(removed.len(), 10);
4420 assert_eq!(removed, thin_vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);
4421
4422 assert_eq!(vec.len(), 10);
4423 assert_eq!(vec, thin_vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
4424 }
4425
4426 { // [+++++++++++xxxxxxxxxx]
4427 let mut vec = thin_vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19,
4428 2, 4, 6, 8, 10, 12, 14, 16, 18, 20];
4429
4430 let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<ThinVec<_>>();
4431 assert_eq!(removed.len(), 10);
4432 assert_eq!(removed, thin_vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);
4433
4434 assert_eq!(vec.len(), 10);
4435 assert_eq!(vec, thin_vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
4436 }
4437 }
4438 */
4439 #[test]
4440 fn test_reserve_exact() {
4441 // This is all the same as test_reserve
4442
4443 let mut v = ThinVec::new();
4444 assert_eq!(v.capacity(), 0);
4445
4446 v.reserve_exact(2);
4447 assert!(v.capacity() >= 2);
4448
4449 for i in 0..16 {
4450 v.push(i);
4451 }
4452
4453 assert!(v.capacity() >= 16);
4454 v.reserve_exact(16);
4455 assert!(v.capacity() >= 32);
4456
4457 v.push(16);
4458
4459 v.reserve_exact(16);
4460 assert!(v.capacity() >= 33)
4461 }
4462
4463 /* TODO: implement try_reserve
4464 #[test]
4465 fn test_try_reserve() {
4466
4467 // These are the interesting cases:
4468 // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM)
4469 // * > isize::MAX should always fail
4470 // * On 16/32-bit should CapacityOverflow
4471 // * On 64-bit should OOM
4472 // * overflow may trigger when adding `len` to `cap` (in number of elements)
4473 // * overflow may trigger when multiplying `new_cap` by size_of::<T> (to get bytes)
4474
4475 const MAX_CAP: usize = isize::MAX as usize;
4476 const MAX_USIZE: usize = usize::MAX;
4477
4478 // On 16/32-bit, we check that allocations don't exceed isize::MAX,
4479 // on 64-bit, we assume the OS will give an OOM for such a ridiculous size.
4480 // Any platform that succeeds for these requests is technically broken with
4481 // ptr::offset because LLVM is the worst.
4482 let guards_against_isize = size_of::<usize>() < 8;
4483
4484 {
4485 // Note: basic stuff is checked by test_reserve
4486 let mut empty_bytes: ThinVec<u8> = ThinVec::new();
4487
4488 // Check isize::MAX doesn't count as an overflow
4489 if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) {
4490 panic!("isize::MAX shouldn't trigger an overflow!");
4491 }
4492 // Play it again, frank! (just to be sure)
4493 if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) {
4494 panic!("isize::MAX shouldn't trigger an overflow!");
4495 }
4496
4497 if guards_against_isize {
4498 // Check isize::MAX + 1 does count as overflow
4499 if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP + 1) {
4500 } else { panic!("isize::MAX + 1 should trigger an overflow!") }
4501
4502 // Check usize::MAX does count as overflow
4503 if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) {
4504 } else { panic!("usize::MAX should trigger an overflow!") }
4505 } else {
4506 // Check isize::MAX + 1 is an OOM
4507 if let Err(AllocErr) = empty_bytes.try_reserve(MAX_CAP + 1) {
4508 } else { panic!("isize::MAX + 1 should trigger an OOM!") }
4509
4510 // Check usize::MAX is an OOM
4511 if let Err(AllocErr) = empty_bytes.try_reserve(MAX_USIZE) {
4512 } else { panic!("usize::MAX should trigger an OOM!") }
4513 }
4514 }
4515
4516
4517 {
4518 // Same basic idea, but with non-zero len
4519 let mut ten_bytes: ThinVec<u8> = thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
4520
4521 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) {
4522 panic!("isize::MAX shouldn't trigger an overflow!");
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 guards_against_isize {
4528 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) {
4529 } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
4530 } else {
4531 if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) {
4532 } else { panic!("isize::MAX + 1 should trigger an OOM!") }
4533 }
4534 // Should always overflow in the add-to-len
4535 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) {
4536 } else { panic!("usize::MAX should trigger an overflow!") }
4537 }
4538
4539
4540 {
4541 // Same basic idea, but with interesting type size
4542 let mut ten_u32s: ThinVec<u32> = thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
4543
4544 if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 10) {
4545 panic!("isize::MAX shouldn't trigger an overflow!");
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 guards_against_isize {
4551 if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
4552 } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
4553 } else {
4554 if let Err(AllocErr) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
4555 } else { panic!("isize::MAX + 1 should trigger an OOM!") }
4556 }
4557 // Should fail in the mul-by-size
4558 if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_USIZE - 20) {
4559 } else {
4560 panic!("usize::MAX should trigger an overflow!");
4561 }
4562 }
4563
4564 }
4565
4566 #[test]
4567 fn test_try_reserve_exact() {
4568
4569 // This is exactly the same as test_try_reserve with the method changed.
4570 // See that test for comments.
4571
4572 const MAX_CAP: usize = isize::MAX as usize;
4573 const MAX_USIZE: usize = usize::MAX;
4574
4575 let guards_against_isize = size_of::<usize>() < 8;
4576
4577 {
4578 let mut empty_bytes: ThinVec<u8> = ThinVec::new();
4579
4580 if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) {
4581 panic!("isize::MAX shouldn't trigger an overflow!");
4582 }
4583 if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) {
4584 panic!("isize::MAX shouldn't trigger an overflow!");
4585 }
4586
4587 if guards_against_isize {
4588 if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP + 1) {
4589 } else { panic!("isize::MAX + 1 should trigger an overflow!") }
4590
4591 if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_USIZE) {
4592 } else { panic!("usize::MAX should trigger an overflow!") }
4593 } else {
4594 if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_CAP + 1) {
4595 } else { panic!("isize::MAX + 1 should trigger an OOM!") }
4596
4597 if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_USIZE) {
4598 } else { panic!("usize::MAX should trigger an OOM!") }
4599 }
4600 }
4601
4602
4603 {
4604 let mut ten_bytes: ThinVec<u8> = thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
4605
4606 if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) {
4607 panic!("isize::MAX shouldn't trigger an overflow!");
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 guards_against_isize {
4613 if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
4614 } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
4615 } else {
4616 if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
4617 } else { panic!("isize::MAX + 1 should trigger an OOM!") }
4618 }
4619 if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) {
4620 } else { panic!("usize::MAX should trigger an overflow!") }
4621 }
4622
4623
4624 {
4625 let mut ten_u32s: ThinVec<u32> = thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
4626
4627 if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 10) {
4628 panic!("isize::MAX shouldn't trigger an overflow!");
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 guards_against_isize {
4634 if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
4635 } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
4636 } else {
4637 if let Err(AllocErr) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
4638 } else { panic!("isize::MAX + 1 should trigger an OOM!") }
4639 }
4640 if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) {
4641 } else { panic!("usize::MAX should trigger an overflow!") }
4642 }
4643 }
4644 */
4645
4646 #[cfg(feature = "gecko-ffi")]
4647 #[test]
4648 fn auto_t_array_basic() {
4649 crate::auto_thin_vec!(let t: [u8; 10]);
4650 assert_eq!(t.capacity(), 10);
4651 assert!(t.is_auto_array());
4652 assert!(t.uses_stack_allocated_buffer());
4653 assert!(!t.has_allocation());
4654 assert_eq!(t.len(), 0);
4655 {
4656 let inner = unsafe { &mut *t.as_mut().as_mut_ptr() };
4657 for i in 0..30 {
4658 inner.push(i as u8);
4659 }
4660 }
4661
4662 assert!(t.is_auto_array());
4663 assert!(!t.uses_stack_allocated_buffer());
4664 assert_eq!(t.len(), 30);
4665 assert!(t.has_allocation());
4666 assert_eq!(t[5], 5);
4667 assert_eq!(t[29], 29);
4668 assert!(t.capacity() >= 30);
4669
4670 {
4671 let inner = unsafe { &mut *t.as_mut().as_mut_ptr() };
4672 inner.truncate(5);
4673 }
4674
4675 assert_eq!(t.len(), 5);
4676 assert!(t.capacity() >= 30);
4677 assert!(t.has_allocation());
4678 t.as_mut().shrink_to_fit();
4679 assert!(!t.has_allocation());
4680 assert!(t.is_auto_array());
4681 assert!(t.uses_stack_allocated_buffer());
4682 assert_eq!(t.capacity(), 10);
4683 }
4684
4685 #[test]
4686 #[cfg_attr(feature = "gecko-ffi", ignore)]
4687 fn test_header_data() {
4688 macro_rules! assert_aligned_head_ptr {
4689 ($typename:ty) => {{
4690 let v: ThinVec<$typename> = ThinVec::with_capacity(1 /* ensure allocation */);
4691 let head_ptr: *mut $typename = v.data_raw();
4692 assert_eq!(
4693 head_ptr as usize % core::mem::align_of::<$typename>(),
4694 0,
4695 "expected Header::data<{}> to be aligned",
4696 stringify!($typename)
4697 );
4698 }};
4699 }
4700
4701 const HEADER_SIZE: usize = core::mem::size_of::<Header>();
4702 assert_eq!(2 * core::mem::size_of::<usize>(), HEADER_SIZE);
4703
4704 #[repr(C, align(128))]
4705 struct Funky<T>(T);
4706 assert_eq!(padding::<Funky<()>>(), 128 - HEADER_SIZE);
4707 assert_aligned_head_ptr!(Funky<()>);
4708
4709 assert_eq!(padding::<Funky<u8>>(), 128 - HEADER_SIZE);
4710 assert_aligned_head_ptr!(Funky<u8>);
4711
4712 assert_eq!(padding::<Funky<[(); 1024]>>(), 128 - HEADER_SIZE);
4713 assert_aligned_head_ptr!(Funky<[(); 1024]>);
4714
4715 assert_eq!(padding::<Funky<[*mut usize; 1024]>>(), 128 - HEADER_SIZE);
4716 assert_aligned_head_ptr!(Funky<[*mut usize; 1024]>);
4717 }
4718
4719 #[cfg(feature = "serde")]
4720 use serde_test::{assert_tokens, Token};
4721
4722 #[test]
4723 #[cfg(feature = "serde")]
4724 fn test_ser_de_empty() {
4725 let vec = ThinVec::<u32>::new();
4726
4727 assert_tokens(&vec, &[Token::Seq { len: Some(0) }, Token::SeqEnd]);
4728 }
4729
4730 #[test]
4731 #[cfg(feature = "serde")]
4732 fn test_ser_de() {
4733 let mut vec = ThinVec::<u32>::new();
4734 vec.push(20);
4735 vec.push(55);
4736 vec.push(123);
4737
4738 assert_tokens(
4739 &vec,
4740 &[
4741 Token::Seq { len: Some(3) },
4742 Token::U32(20),
4743 Token::U32(55),
4744 Token::U32(123),
4745 Token::SeqEnd,
4746 ],
4747 );
4748 }
4749
4750 #[test]
4751 fn test_set_len() {
4752 let mut vec: ThinVec<u32> = thin_vec![];
4753 unsafe {
4754 vec.set_len(0); // at one point this caused a crash
4755 }
4756 }
4757
4758 #[test]
4759 #[should_panic(expected = "invalid set_len(1) on empty ThinVec")]
4760 fn test_set_len_invalid() {
4761 let mut vec: ThinVec<u32> = thin_vec![];
4762 unsafe {
4763 vec.set_len(1);
4764 }
4765 }
4766
4767 #[test]
4768 #[should_panic(expected = "capacity overflow")]
4769 fn test_capacity_overflow_header_too_big() {
4770 let vec: ThinVec<u8> = ThinVec::with_capacity(isize::MAX as usize - 2);
4771 assert!(vec.capacity() > 0);
4772 }
4773 #[test]
4774 #[should_panic(expected = "capacity overflow")]
4775 fn test_capacity_overflow_cap_too_big() {
4776 let vec: ThinVec<u8> = ThinVec::with_capacity(isize::MAX as usize + 1);
4777 assert!(vec.capacity() > 0);
4778 }
4779 #[test]
4780 #[should_panic(expected = "capacity overflow")]
4781 fn test_capacity_overflow_size_mul1() {
4782 let vec: ThinVec<u16> = ThinVec::with_capacity(isize::MAX as usize + 1);
4783 assert!(vec.capacity() > 0);
4784 }
4785 #[test]
4786 #[should_panic(expected = "capacity overflow")]
4787 fn test_capacity_overflow_size_mul2() {
4788 let vec: ThinVec<u16> = ThinVec::with_capacity(isize::MAX as usize / 2 + 1);
4789 assert!(vec.capacity() > 0);
4790 }
4791 #[test]
4792 #[should_panic(expected = "capacity overflow")]
4793 fn test_capacity_overflow_cap_really_isnt_isize() {
4794 let vec: ThinVec<u8> = ThinVec::with_capacity(isize::MAX as usize);
4795 assert!(vec.capacity() > 0);
4796 }
4797
4798 struct PanicBomb(&'static str);
4799
4800 impl Drop for PanicBomb {
4801 fn drop(&mut self) {
4802 if self.0 == "panic" {
4803 panic!("panic!");
4804 }
4805 }
4806 }
4807
4808 #[test]
4809 #[should_panic(expected = "panic!")]
4810 fn test_panic_into_iter() {
4811 let mut v = ThinVec::new();
4812 v.push(PanicBomb("normal1"));
4813 v.push(PanicBomb("panic"));
4814 v.push(PanicBomb("normal2"));
4815
4816 let mut iter = v.into_iter();
4817 iter.next();
4818 }
4819
4820 #[test]
4821 #[should_panic(expected = "panic!")]
4822 fn test_panic_clear() {
4823 let mut v = ThinVec::new();
4824 v.push(PanicBomb("normal1"));
4825 v.push(PanicBomb("panic"));
4826 v.push(PanicBomb("normal2"));
4827 v.clear();
4828 }
4829}