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 ptr::drop_in_place(&mut self[..]);
1085 self.set_len(0); // could be the singleton
1086 }
1087 }
1088
1089 /// Extracts a slice containing the entire vector.
1090 ///
1091 /// Equivalent to `&s[..]`.
1092 ///
1093 /// # Examples
1094 ///
1095 /// ```
1096 /// use thin_vec::thin_vec;
1097 /// use std::io::{self, Write};
1098 /// let buffer = thin_vec![1, 2, 3, 5, 8];
1099 /// io::sink().write(buffer.as_slice()).unwrap();
1100 /// ```
1101 pub fn as_slice(&self) -> &[T] {
1102 unsafe { slice::from_raw_parts(self.data_raw(), self.len()) }
1103 }
1104
1105 /// Extracts a mutable slice of the entire vector.
1106 ///
1107 /// Equivalent to `&mut s[..]`.
1108 ///
1109 /// # Examples
1110 ///
1111 /// ```
1112 /// use thin_vec::thin_vec;
1113 /// use std::io::{self, Read};
1114 /// let mut buffer = vec![0; 3];
1115 /// io::repeat(0b101).read_exact(buffer.as_mut_slice()).unwrap();
1116 /// ```
1117 pub fn as_mut_slice(&mut self) -> &mut [T] {
1118 unsafe { slice::from_raw_parts_mut(self.data_raw(), self.len()) }
1119 }
1120
1121 /// Reserve capacity for at least `additional` more elements to be inserted.
1122 ///
1123 /// May reserve more space than requested, to avoid frequent reallocations.
1124 ///
1125 /// Panics if the new capacity overflows `usize`.
1126 ///
1127 /// Re-allocates only if `self.capacity() < self.len() + additional`.
1128 #[cfg(not(feature = "gecko-ffi"))]
1129 pub fn reserve(&mut self, additional: usize) {
1130 let len = self.len();
1131 let old_cap = self.capacity();
1132 let min_cap = len.checked_add(additional).unwrap_cap_overflow();
1133 if min_cap <= old_cap {
1134 return;
1135 }
1136 // Ensure the new capacity is at least double, to guarantee exponential growth.
1137 let double_cap = if old_cap == 0 {
1138 // skip to 4 because tiny ThinVecs are dumb; but not if that would cause overflow
1139 if mem::size_of::<T>() > (!0) / 8 {
1140 1
1141 } else {
1142 4
1143 }
1144 } else {
1145 old_cap.saturating_mul(2)
1146 };
1147 let new_cap = max(min_cap, double_cap);
1148 unsafe {
1149 self.reallocate(new_cap);
1150 }
1151 }
1152
1153 /// Reserve capacity for at least `additional` more elements to be inserted.
1154 ///
1155 /// This method mimics the growth algorithm used by the C++ implementation
1156 /// of nsTArray.
1157 #[cfg(feature = "gecko-ffi")]
1158 pub fn reserve(&mut self, additional: usize) {
1159 let elem_size = mem::size_of::<T>();
1160
1161 let len = self.len();
1162 let old_cap = self.capacity();
1163 let min_cap = len.checked_add(additional).unwrap_cap_overflow();
1164 if min_cap <= old_cap {
1165 return;
1166 }
1167
1168 // The growth logic can't handle zero-sized types, so we have to exit
1169 // early here.
1170 if elem_size == 0 {
1171 unsafe {
1172 self.reallocate(min_cap);
1173 }
1174 return;
1175 }
1176
1177 let min_cap_bytes = assert_size(min_cap)
1178 .checked_mul(assert_size(elem_size))
1179 .and_then(|x| x.checked_add(assert_size(mem::size_of::<Header>())))
1180 .unwrap();
1181
1182 // Perform some checked arithmetic to ensure all of the numbers we
1183 // compute will end up in range.
1184 let will_fit = min_cap_bytes.checked_mul(2).is_some();
1185 if !will_fit {
1186 panic!("Exceeded maximum nsTArray size");
1187 }
1188
1189 const SLOW_GROWTH_THRESHOLD: usize = 8 * 1024 * 1024;
1190
1191 let bytes = if min_cap > SLOW_GROWTH_THRESHOLD {
1192 // Grow by a minimum of 1.125x
1193 let old_cap_bytes = old_cap * elem_size + mem::size_of::<Header>();
1194 let min_growth = old_cap_bytes + (old_cap_bytes >> 3);
1195 let growth = max(min_growth, min_cap_bytes as usize);
1196
1197 // Round up to the next megabyte.
1198 const MB: usize = 1 << 20;
1199 MB * ((growth + MB - 1) / MB)
1200 } else {
1201 // Try to allocate backing buffers in powers of two.
1202 min_cap_bytes.next_power_of_two() as usize
1203 };
1204
1205 let cap = (bytes - core::mem::size_of::<Header>()) / elem_size;
1206 unsafe {
1207 self.reallocate(cap);
1208 }
1209 }
1210
1211 /// Reserves the minimum capacity for `additional` more elements to be inserted.
1212 ///
1213 /// Panics if the new capacity overflows `usize`.
1214 ///
1215 /// Re-allocates only if `self.capacity() < self.len() + additional`.
1216 pub fn reserve_exact(&mut self, additional: usize) {
1217 let new_cap = self.len().checked_add(additional).unwrap_cap_overflow();
1218 let old_cap = self.capacity();
1219 if new_cap > old_cap {
1220 unsafe {
1221 self.reallocate(new_cap);
1222 }
1223 }
1224 }
1225
1226 /// Shrinks the capacity of the vector as much as possible.
1227 ///
1228 /// It will drop down as close as possible to the length but the allocator
1229 /// may still inform the vector that there is space for a few more elements.
1230 ///
1231 /// # Examples
1232 ///
1233 /// ```
1234 /// use thin_vec::ThinVec;
1235 ///
1236 /// let mut vec = ThinVec::with_capacity(10);
1237 /// vec.extend([1, 2, 3]);
1238 /// assert_eq!(vec.capacity(), 10);
1239 /// vec.shrink_to_fit();
1240 /// assert!(vec.capacity() >= 3);
1241 /// ```
1242 pub fn shrink_to_fit(&mut self) {
1243 let old_cap = self.capacity();
1244 let new_cap = self.len();
1245 if new_cap >= old_cap {
1246 return;
1247 }
1248 #[cfg(feature = "gecko-ffi")]
1249 unsafe {
1250 let stack_buf = self.auto_array_header_mut();
1251 if !stack_buf.is_null() && (*stack_buf).cap() >= new_cap {
1252 // Try to switch to our auto-buffer.
1253 if stack_buf == self.ptr.as_ptr() {
1254 return;
1255 }
1256 stack_buf
1257 .add(1)
1258 .cast::<T>()
1259 .copy_from_nonoverlapping(self.data_raw(), new_cap);
1260 dealloc(self.ptr() as *mut u8, layout::<T>(old_cap));
1261 self.ptr = NonNull::new_unchecked(stack_buf);
1262 self.ptr.as_mut().set_len(new_cap);
1263 return;
1264 }
1265 }
1266 if new_cap == 0 {
1267 *self = ThinVec::new();
1268 } else {
1269 unsafe {
1270 self.reallocate(new_cap);
1271 }
1272 }
1273 }
1274
1275 /// Retains only the elements specified by the predicate.
1276 ///
1277 /// In other words, remove all elements `e` such that `f(&e)` returns `false`.
1278 /// This method operates in place and preserves the order of the retained
1279 /// elements.
1280 ///
1281 /// # Examples
1282 ///
1283 // A hack to avoid linking problems with `cargo test --features=gecko-ffi`.
1284 #[cfg_attr(not(feature = "gecko-ffi"), doc = "```")]
1285 #[cfg_attr(feature = "gecko-ffi", doc = "```ignore")]
1286 /// # #[macro_use] extern crate thin_vec;
1287 /// # fn main() {
1288 /// let mut vec = thin_vec![1, 2, 3, 4];
1289 /// vec.retain(|&x| x%2 == 0);
1290 /// assert_eq!(vec, [2, 4]);
1291 /// # }
1292 /// ```
1293 pub fn retain<F>(&mut self, mut f: F)
1294 where
1295 F: FnMut(&T) -> bool,
1296 {
1297 self.retain_mut(|x| f(&*x));
1298 }
1299
1300 /// Retains only the elements specified by the predicate, passing a mutable reference to it.
1301 ///
1302 /// In other words, remove all elements `e` such that `f(&mut e)` returns `false`.
1303 /// This method operates in place and preserves the order of the retained
1304 /// elements.
1305 ///
1306 /// # Examples
1307 ///
1308 // A hack to avoid linking problems with `cargo test --features=gecko-ffi`.
1309 #[cfg_attr(not(feature = "gecko-ffi"), doc = "```")]
1310 #[cfg_attr(feature = "gecko-ffi", doc = "```ignore")]
1311 /// # #[macro_use] extern crate thin_vec;
1312 /// # fn main() {
1313 /// let mut vec = thin_vec![1, 2, 3, 4, 5];
1314 /// vec.retain_mut(|x| {
1315 /// *x += 1;
1316 /// (*x)%2 == 0
1317 /// });
1318 /// assert_eq!(vec, [2, 4, 6]);
1319 /// # }
1320 /// ```
1321 pub fn retain_mut<F>(&mut self, mut f: F)
1322 where
1323 F: FnMut(&mut T) -> bool,
1324 {
1325 let len = self.len();
1326 let mut del = 0;
1327 {
1328 let v = &mut self[..];
1329
1330 for i in 0..len {
1331 if !f(&mut v[i]) {
1332 del += 1;
1333 } else if del > 0 {
1334 v.swap(i - del, i);
1335 }
1336 }
1337 }
1338 if del > 0 {
1339 self.truncate(len - del);
1340 }
1341 }
1342
1343 /// Removes consecutive elements in the vector that resolve to the same key.
1344 ///
1345 /// If the vector is sorted, this removes all duplicates.
1346 ///
1347 /// # Examples
1348 ///
1349 // A hack to avoid linking problems with `cargo test --features=gecko-ffi`.
1350 #[cfg_attr(not(feature = "gecko-ffi"), doc = "```")]
1351 #[cfg_attr(feature = "gecko-ffi", doc = "```ignore")]
1352 /// # #[macro_use] extern crate thin_vec;
1353 /// # fn main() {
1354 /// let mut vec = thin_vec![10, 20, 21, 30, 20];
1355 ///
1356 /// vec.dedup_by_key(|i| *i / 10);
1357 ///
1358 /// assert_eq!(vec, [10, 20, 30, 20]);
1359 /// # }
1360 /// ```
1361 pub fn dedup_by_key<F, K>(&mut self, mut key: F)
1362 where
1363 F: FnMut(&mut T) -> K,
1364 K: PartialEq<K>,
1365 {
1366 self.dedup_by(|a, b| key(a) == key(b))
1367 }
1368
1369 /// Removes consecutive elements in the vector according to a predicate.
1370 ///
1371 /// The `same_bucket` function is passed references to two elements from the vector, and
1372 /// returns `true` if the elements compare equal, or `false` if they do not. Only the first
1373 /// of adjacent equal items is kept.
1374 ///
1375 /// If the vector is sorted, this removes all duplicates.
1376 ///
1377 /// # Examples
1378 ///
1379 // A hack to avoid linking problems with `cargo test --features=gecko-ffi`.
1380 #[cfg_attr(not(feature = "gecko-ffi"), doc = "```")]
1381 #[cfg_attr(feature = "gecko-ffi", doc = "```ignore")]
1382 /// # #[macro_use] extern crate thin_vec;
1383 /// # fn main() {
1384 /// let mut vec = thin_vec!["foo", "bar", "Bar", "baz", "bar"];
1385 ///
1386 /// vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
1387 ///
1388 /// assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
1389 /// # }
1390 /// ```
1391 #[allow(clippy::swap_ptr_to_ref)]
1392 pub fn dedup_by<F>(&mut self, mut same_bucket: F)
1393 where
1394 F: FnMut(&mut T, &mut T) -> bool,
1395 {
1396 // See the comments in `Vec::dedup` for a detailed explanation of this code.
1397 unsafe {
1398 let ln = self.len();
1399 if ln <= 1 {
1400 return;
1401 }
1402
1403 // Avoid bounds checks by using raw pointers.
1404 let p = self.as_mut_ptr();
1405 let mut r: usize = 1;
1406 let mut w: usize = 1;
1407
1408 while r < ln {
1409 let p_r = p.add(r);
1410 let p_wm1 = p.add(w - 1);
1411 if !same_bucket(&mut *p_r, &mut *p_wm1) {
1412 if r != w {
1413 let p_w = p_wm1.add(1);
1414 mem::swap(&mut *p_r, &mut *p_w);
1415 }
1416 w += 1;
1417 }
1418 r += 1;
1419 }
1420
1421 self.truncate(w);
1422 }
1423 }
1424
1425 /// Splits the collection into two at the given index.
1426 ///
1427 /// Returns a newly allocated vector containing the elements in the range
1428 /// `[at, len)`. After the call, the original vector will be left containing
1429 /// the elements `[0, at)` with its previous capacity unchanged.
1430 ///
1431 /// # Panics
1432 ///
1433 /// Panics if `at > len`.
1434 ///
1435 /// # Examples
1436 ///
1437 /// ```
1438 /// use thin_vec::thin_vec;
1439 ///
1440 /// let mut vec = thin_vec![1, 2, 3];
1441 /// let vec2 = vec.split_off(1);
1442 /// assert_eq!(vec, [1]);
1443 /// assert_eq!(vec2, [2, 3]);
1444 /// ```
1445 pub fn split_off(&mut self, at: usize) -> ThinVec<T> {
1446 let old_len = self.len();
1447 let new_vec_len = old_len - at;
1448
1449 assert!(at <= old_len, "Index out of bounds");
1450
1451 unsafe {
1452 let mut new_vec = ThinVec::with_capacity(new_vec_len);
1453
1454 ptr::copy_nonoverlapping(self.data_raw().add(at), new_vec.data_raw(), new_vec_len);
1455
1456 new_vec.set_len(new_vec_len); // could be the singleton
1457 self.set_len(at); // could be the singleton
1458
1459 new_vec
1460 }
1461 }
1462
1463 /// Moves all the elements of `other` into `self`, leaving `other` empty.
1464 ///
1465 /// # Panics
1466 ///
1467 /// Panics if the new capacity exceeds `isize::MAX` bytes.
1468 ///
1469 /// # Examples
1470 ///
1471 /// ```
1472 /// use thin_vec::thin_vec;
1473 ///
1474 /// let mut vec = thin_vec![1, 2, 3];
1475 /// let mut vec2 = thin_vec![4, 5, 6];
1476 /// vec.append(&mut vec2);
1477 /// assert_eq!(vec, [1, 2, 3, 4, 5, 6]);
1478 /// assert_eq!(vec2, []);
1479 /// ```
1480 pub fn append(&mut self, other: &mut ThinVec<T>) {
1481 self.extend(other.drain(..))
1482 }
1483
1484 /// Removes the specified range from the vector in bulk, returning all
1485 /// removed elements as an iterator. If the iterator is dropped before
1486 /// being fully consumed, it drops the remaining removed elements.
1487 ///
1488 /// The returned iterator keeps a mutable borrow on the vector to optimize
1489 /// its implementation.
1490 ///
1491 /// # Panics
1492 ///
1493 /// Panics if the starting point is greater than the end point or if
1494 /// the end point is greater than the length of the vector.
1495 ///
1496 /// # Leaking
1497 ///
1498 /// If the returned iterator goes out of scope without being dropped (due to
1499 /// [`mem::forget`], for example), the vector may have lost and leaked
1500 /// elements arbitrarily, including elements outside the range.
1501 ///
1502 /// # Examples
1503 ///
1504 /// ```
1505 /// use thin_vec::{ThinVec, thin_vec};
1506 ///
1507 /// let mut v = thin_vec![1, 2, 3];
1508 /// let u: ThinVec<_> = v.drain(1..).collect();
1509 /// assert_eq!(v, &[1]);
1510 /// assert_eq!(u, &[2, 3]);
1511 ///
1512 /// // A full range clears the vector, like `clear()` does
1513 /// v.drain(..);
1514 /// assert_eq!(v, &[]);
1515 /// ```
1516 pub fn drain<R>(&mut self, range: R) -> Drain<'_, T>
1517 where
1518 R: RangeBounds<usize>,
1519 {
1520 // See comments in the Drain struct itself for details on this
1521 let len = self.len();
1522 let start = match range.start_bound() {
1523 Bound::Included(&n) => n,
1524 Bound::Excluded(&n) => n + 1,
1525 Bound::Unbounded => 0,
1526 };
1527 let end = match range.end_bound() {
1528 Bound::Included(&n) => n + 1,
1529 Bound::Excluded(&n) => n,
1530 Bound::Unbounded => len,
1531 };
1532 assert!(start <= end);
1533 assert!(end <= len);
1534
1535 unsafe {
1536 // Set our length to the start bound
1537 self.set_len(start); // could be the singleton
1538
1539 let iter = slice::from_raw_parts(self.data_raw().add(start), end - start).iter();
1540
1541 Drain {
1542 iter,
1543 vec: NonNull::from(self),
1544 end,
1545 tail: len - end,
1546 }
1547 }
1548 }
1549
1550 /// Creates a splicing iterator that replaces the specified range in the vector
1551 /// with the given `replace_with` iterator and yields the removed items.
1552 /// `replace_with` does not need to be the same length as `range`.
1553 ///
1554 /// `range` is removed even if the iterator is not consumed until the end.
1555 ///
1556 /// It is unspecified how many elements are removed from the vector
1557 /// if the `Splice` value is leaked.
1558 ///
1559 /// The input iterator `replace_with` is only consumed when the `Splice` value is dropped.
1560 ///
1561 /// This is optimal if:
1562 ///
1563 /// * The tail (elements in the vector after `range`) is empty,
1564 /// * or `replace_with` yields fewer or equal elements than `range`’s length
1565 /// * or the lower bound of its `size_hint()` is exact.
1566 ///
1567 /// Otherwise, a temporary vector is allocated and the tail is moved twice.
1568 ///
1569 /// # Panics
1570 ///
1571 /// Panics if the starting point is greater than the end point or if
1572 /// the end point is greater than the length of the vector.
1573 ///
1574 /// # Examples
1575 ///
1576 /// ```
1577 /// use thin_vec::{ThinVec, thin_vec};
1578 ///
1579 /// let mut v = thin_vec![1, 2, 3, 4];
1580 /// let new = [7, 8, 9];
1581 /// let u: ThinVec<_> = v.splice(1..3, new).collect();
1582 /// assert_eq!(v, &[1, 7, 8, 9, 4]);
1583 /// assert_eq!(u, &[2, 3]);
1584 /// ```
1585 #[inline]
1586 pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter>
1587 where
1588 R: RangeBounds<usize>,
1589 I: IntoIterator<Item = T>,
1590 {
1591 Splice {
1592 drain: self.drain(range),
1593 replace_with: replace_with.into_iter(),
1594 }
1595 }
1596
1597 /// Creates an iterator which uses a closure to determine if an element should be removed.
1598 ///
1599 /// If the closure returns true, then the element is removed and yielded.
1600 /// If the closure returns false, the element will remain in the vector and will not be yielded
1601 /// by the iterator.
1602 ///
1603 /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating
1604 /// or the iteration short-circuits, then the remaining elements will be retained.
1605 /// Use [`ThinVec::retain`] with a negated predicate if you do not need the returned iterator.
1606 ///
1607 /// Using this method is equivalent to the following code:
1608 ///
1609 /// ```
1610 /// # use thin_vec::{ThinVec, thin_vec};
1611 /// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 };
1612 /// # let mut vec = thin_vec![1, 2, 3, 4, 5, 6];
1613 /// let mut i = 0;
1614 /// while i < vec.len() {
1615 /// if some_predicate(&mut vec[i]) {
1616 /// let val = vec.remove(i);
1617 /// // your code here
1618 /// } else {
1619 /// i += 1;
1620 /// }
1621 /// }
1622 ///
1623 /// # assert_eq!(vec, thin_vec![1, 4, 5]);
1624 /// ```
1625 ///
1626 /// But `extract_if` is easier to use. `extract_if` is also more efficient,
1627 /// because it can backshift the elements of the array in bulk.
1628 ///
1629 /// Note that `extract_if` also lets you mutate every element in the filter closure,
1630 /// regardless of whether you choose to keep or remove it.
1631 ///
1632 /// # Examples
1633 ///
1634 /// Splitting an array into evens and odds, reusing the original allocation:
1635 ///
1636 /// ```
1637 /// use thin_vec::{ThinVec, thin_vec};
1638 ///
1639 /// let mut numbers = thin_vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15];
1640 ///
1641 /// let evens = numbers.extract_if(.., |x| *x % 2 == 0).collect::<ThinVec<_>>();
1642 /// let odds = numbers;
1643 ///
1644 /// assert_eq!(evens, thin_vec![2, 4, 6, 8, 14]);
1645 /// assert_eq!(odds, thin_vec![1, 3, 5, 9, 11, 13, 15]);
1646 /// ```
1647 pub fn extract_if<F, R: RangeBounds<usize>>(
1648 &mut self,
1649 range: R,
1650 filter: F,
1651 ) -> ExtractIf<'_, T, F>
1652 where
1653 F: FnMut(&mut T) -> bool,
1654 {
1655 // Copy of https://github.com/rust-lang/rust/blob/ee361e8fca1c30e13e7a31cc82b64c045339d3a8/library/core/src/slice/index.rs#L37
1656 fn slice_index_fail(start: usize, end: usize, len: usize) -> ! {
1657 if start > len {
1658 panic!(
1659 "range start index {} out of range for slice of length {}",
1660 start, len
1661 )
1662 }
1663
1664 if end > len {
1665 panic!(
1666 "range end index {} out of range for slice of length {}",
1667 end, len
1668 )
1669 }
1670
1671 if start > end {
1672 panic!("slice index starts at {} but ends at {}", start, end)
1673 }
1674
1675 // Only reachable if the range was a `RangeInclusive` or a
1676 // `RangeToInclusive`, with `end == len`.
1677 panic!(
1678 "range end index {} out of range for slice of length {}",
1679 end, len
1680 )
1681 }
1682
1683 // Backport of https://github.com/rust-lang/rust/blob/ee361e8fca1c30e13e7a31cc82b64c045339d3a8/library/core/src/slice/index.rs#L855
1684 pub fn slice_range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize>
1685 where
1686 R: ops::RangeBounds<usize>,
1687 {
1688 let len = bounds.end;
1689
1690 let end = match range.end_bound() {
1691 ops::Bound::Included(&end) if end >= len => slice_index_fail(0, end, len),
1692 // Cannot overflow because `end < len` implies `end < usize::MAX`.
1693 ops::Bound::Included(&end) => end + 1,
1694
1695 ops::Bound::Excluded(&end) if end > len => slice_index_fail(0, end, len),
1696 ops::Bound::Excluded(&end) => end,
1697 ops::Bound::Unbounded => len,
1698 };
1699
1700 let start = match range.start_bound() {
1701 ops::Bound::Excluded(&start) if start >= end => slice_index_fail(start, end, len),
1702 // Cannot overflow because `start < end` implies `start < usize::MAX`.
1703 ops::Bound::Excluded(&start) => start + 1,
1704
1705 ops::Bound::Included(&start) if start > end => slice_index_fail(start, end, len),
1706 ops::Bound::Included(&start) => start,
1707
1708 ops::Bound::Unbounded => 0,
1709 };
1710
1711 ops::Range { start, end }
1712 }
1713
1714 let old_len = self.len();
1715 let ops::Range { start, end } = slice_range(range, ..old_len);
1716
1717 // Guard against the vec getting leaked (leak amplification)
1718 unsafe {
1719 self.set_len(0);
1720 }
1721 ExtractIf {
1722 vec: self,
1723 idx: start,
1724 del: 0,
1725 end,
1726 old_len,
1727 pred: filter,
1728 }
1729 }
1730
1731 /// Resize the buffer and update its capacity, without changing the length.
1732 /// Unsafe because it can cause length to be greater than capacity.
1733 unsafe fn reallocate(&mut self, new_cap: usize) {
1734 debug_assert!(new_cap > 0);
1735 if self.has_allocation() {
1736 let old_cap = self.capacity();
1737 let ptr = realloc(
1738 self.ptr() as *mut u8,
1739 layout::<T>(old_cap),
1740 alloc_size::<T>(new_cap),
1741 ) as *mut Header;
1742
1743 if ptr.is_null() {
1744 handle_alloc_error(layout::<T>(new_cap))
1745 }
1746 (*ptr).set_cap_and_auto(new_cap, (*ptr).is_auto());
1747 self.ptr = NonNull::new_unchecked(ptr);
1748 } else {
1749 let new_header = header_with_capacity::<T>(new_cap, self.is_auto_array());
1750
1751 // If we get here and have a non-zero len, then we must be handling
1752 // a gecko auto array, and we have items in a stack buffer. We shouldn't
1753 // free it, but we should memcopy the contents out of it and mark it as empty.
1754 //
1755 // T is assumed to be trivially relocatable, as this is ~required
1756 // for Rust compatibility anyway. Furthermore, we assume C++ won't try
1757 // to unconditionally destroy the contents of the stack allocated buffer
1758 // (i.e. it's obfuscated behind a union).
1759 //
1760 // In effect, we are partially reimplementing the auto array move constructor
1761 // by leaving behind a valid empty instance.
1762 let len = self.len();
1763 if cfg!(feature = "gecko-ffi") && len > 0 {
1764 new_header
1765 .as_ptr()
1766 .add(1)
1767 .cast::<T>()
1768 .copy_from_nonoverlapping(self.data_raw(), len);
1769 self.set_len_non_singleton(0);
1770 }
1771
1772 self.ptr = new_header;
1773 }
1774 }
1775
1776 #[inline]
1777 #[allow(unused_unsafe)]
1778 fn is_singleton(&self) -> bool {
1779 unsafe { self.ptr.as_ptr() as *const Header == &EMPTY_HEADER }
1780 }
1781
1782 #[cfg(feature = "gecko-ffi")]
1783 #[inline]
1784 fn auto_array_header_mut(&mut self) -> *mut Header {
1785 if !self.is_auto_array() {
1786 return ptr::null_mut();
1787 }
1788 unsafe { (self as *mut Self).byte_add(AUTO_ARRAY_HEADER_OFFSET) as *mut Header }
1789 }
1790
1791 #[cfg(feature = "gecko-ffi")]
1792 #[inline]
1793 fn auto_array_header(&self) -> *const Header {
1794 if !self.is_auto_array() {
1795 return ptr::null_mut();
1796 }
1797 unsafe { (self as *const Self).byte_add(AUTO_ARRAY_HEADER_OFFSET) as *const Header }
1798 }
1799
1800 #[inline]
1801 fn is_auto_array(&self) -> bool {
1802 unsafe { self.ptr.as_ref().is_auto() }
1803 }
1804
1805 #[inline]
1806 fn uses_stack_allocated_buffer(&self) -> bool {
1807 #[cfg(feature = "gecko-ffi")]
1808 return self.auto_array_header() == self.ptr.as_ptr();
1809 #[cfg(not(feature = "gecko-ffi"))]
1810 return false;
1811 }
1812
1813 #[inline]
1814 fn has_allocation(&self) -> bool {
1815 !self.is_singleton() && !self.uses_stack_allocated_buffer()
1816 }
1817}
1818
1819impl<T: Clone> ThinVec<T> {
1820 /// Resizes the `Vec` in-place so that `len()` is equal to `new_len`.
1821 ///
1822 /// If `new_len` is greater than `len()`, the `Vec` is extended by the
1823 /// difference, with each additional slot filled with `value`.
1824 /// If `new_len` is less than `len()`, the `Vec` is simply truncated.
1825 ///
1826 /// # Examples
1827 ///
1828 // A hack to avoid linking problems with `cargo test --features=gecko-ffi`.
1829 #[cfg_attr(not(feature = "gecko-ffi"), doc = "```")]
1830 #[cfg_attr(feature = "gecko-ffi", doc = "```ignore")]
1831 /// # #[macro_use] extern crate thin_vec;
1832 /// # fn main() {
1833 /// let mut vec = thin_vec!["hello"];
1834 /// vec.resize(3, "world");
1835 /// assert_eq!(vec, ["hello", "world", "world"]);
1836 ///
1837 /// let mut vec = thin_vec![1, 2, 3, 4];
1838 /// vec.resize(2, 0);
1839 /// assert_eq!(vec, [1, 2]);
1840 /// # }
1841 /// ```
1842 pub fn resize(&mut self, new_len: usize, value: T) {
1843 let old_len = self.len();
1844
1845 if new_len > old_len {
1846 let additional = new_len - old_len;
1847 self.reserve(additional);
1848 for _ in 1..additional {
1849 self.push(value.clone());
1850 }
1851 // We can write the last element directly without cloning needlessly
1852 if additional > 0 {
1853 self.push(value);
1854 }
1855 } else if new_len < old_len {
1856 self.truncate(new_len);
1857 }
1858 }
1859
1860 /// Clones and appends all elements in a slice to the `ThinVec`.
1861 ///
1862 /// Iterates over the slice `other`, clones each element, and then appends
1863 /// it to this `ThinVec`. The `other` slice is traversed in-order.
1864 ///
1865 /// Note that this function is same as [`extend`] except that it is
1866 /// specialized to work with slices instead. If and when Rust gets
1867 /// specialization this function will likely be deprecated (but still
1868 /// available).
1869 ///
1870 /// # Examples
1871 ///
1872 /// ```
1873 /// use thin_vec::thin_vec;
1874 ///
1875 /// let mut vec = thin_vec![1];
1876 /// vec.extend_from_slice(&[2, 3, 4]);
1877 /// assert_eq!(vec, [1, 2, 3, 4]);
1878 /// ```
1879 ///
1880 /// [`extend`]: ThinVec::extend
1881 pub fn extend_from_slice(&mut self, other: &[T]) {
1882 self.extend(other.iter().cloned())
1883 }
1884}
1885
1886impl<T: PartialEq> ThinVec<T> {
1887 /// Removes consecutive repeated elements in the vector.
1888 ///
1889 /// If the vector is sorted, this removes all duplicates.
1890 ///
1891 /// # Examples
1892 ///
1893 // A hack to avoid linking problems with `cargo test --features=gecko-ffi`.
1894 #[cfg_attr(not(feature = "gecko-ffi"), doc = "```")]
1895 #[cfg_attr(feature = "gecko-ffi", doc = "```ignore")]
1896 /// # #[macro_use] extern crate thin_vec;
1897 /// # fn main() {
1898 /// let mut vec = thin_vec![1, 2, 2, 3, 2];
1899 ///
1900 /// vec.dedup();
1901 ///
1902 /// assert_eq!(vec, [1, 2, 3, 2]);
1903 /// # }
1904 /// ```
1905 pub fn dedup(&mut self) {
1906 self.dedup_by(|a, b| a == b)
1907 }
1908}
1909
1910impl<T> Drop for ThinVec<T> {
1911 #[inline]
1912 fn drop(&mut self) {
1913 #[cold]
1914 #[inline(never)]
1915 fn drop_non_singleton<T>(this: &mut ThinVec<T>) {
1916 unsafe {
1917 ptr::drop_in_place(&mut this[..]);
1918
1919 if this.uses_stack_allocated_buffer() {
1920 return;
1921 }
1922
1923 dealloc(this.ptr() as *mut u8, layout::<T>(this.capacity()))
1924 }
1925 }
1926
1927 if !self.is_singleton() {
1928 drop_non_singleton(self);
1929 }
1930 }
1931}
1932
1933impl<T> Deref for ThinVec<T> {
1934 type Target = [T];
1935
1936 fn deref(&self) -> &[T] {
1937 self.as_slice()
1938 }
1939}
1940
1941impl<T> DerefMut for ThinVec<T> {
1942 fn deref_mut(&mut self) -> &mut [T] {
1943 self.as_mut_slice()
1944 }
1945}
1946
1947impl<T> Borrow<[T]> for ThinVec<T> {
1948 fn borrow(&self) -> &[T] {
1949 self.as_slice()
1950 }
1951}
1952
1953impl<T> BorrowMut<[T]> for ThinVec<T> {
1954 fn borrow_mut(&mut self) -> &mut [T] {
1955 self.as_mut_slice()
1956 }
1957}
1958
1959impl<T> AsRef<[T]> for ThinVec<T> {
1960 fn as_ref(&self) -> &[T] {
1961 self.as_slice()
1962 }
1963}
1964
1965impl<T> Extend<T> for ThinVec<T> {
1966 #[inline]
1967 fn extend<I>(&mut self, iter: I)
1968 where
1969 I: IntoIterator<Item = T>,
1970 {
1971 let mut iter = iter.into_iter();
1972 let hint = iter.size_hint().0;
1973 if hint > 0 {
1974 self.reserve(hint);
1975 for x in iter.by_ref().take(hint) {
1976 // SAFETY: `reserve(hint)` ensures the next `hint` calls of `push_unchecked`
1977 // have sufficient capacity.
1978 unsafe {
1979 self.push_unchecked(x);
1980 }
1981 }
1982 }
1983
1984 // if the hint underestimated the iterator length,
1985 // push the remaining items with capacity check each time.
1986 for x in iter {
1987 self.push(x);
1988 }
1989 }
1990}
1991
1992impl<T: fmt::Debug> fmt::Debug for ThinVec<T> {
1993 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1994 fmt::Debug::fmt(&**self, f)
1995 }
1996}
1997
1998impl<T> Hash for ThinVec<T>
1999where
2000 T: Hash,
2001{
2002 fn hash<H>(&self, state: &mut H)
2003 where
2004 H: Hasher,
2005 {
2006 self[..].hash(state);
2007 }
2008}
2009
2010impl<T> PartialOrd for ThinVec<T>
2011where
2012 T: PartialOrd,
2013{
2014 #[inline]
2015 fn partial_cmp(&self, other: &ThinVec<T>) -> Option<Ordering> {
2016 self[..].partial_cmp(&other[..])
2017 }
2018}
2019
2020impl<T> Ord for ThinVec<T>
2021where
2022 T: Ord,
2023{
2024 #[inline]
2025 fn cmp(&self, other: &ThinVec<T>) -> Ordering {
2026 self[..].cmp(&other[..])
2027 }
2028}
2029
2030impl<A, B> PartialEq<ThinVec<B>> for ThinVec<A>
2031where
2032 A: PartialEq<B>,
2033{
2034 #[inline]
2035 fn eq(&self, other: &ThinVec<B>) -> bool {
2036 self[..] == other[..]
2037 }
2038}
2039
2040impl<A, B> PartialEq<Vec<B>> for ThinVec<A>
2041where
2042 A: PartialEq<B>,
2043{
2044 #[inline]
2045 fn eq(&self, other: &Vec<B>) -> bool {
2046 self[..] == other[..]
2047 }
2048}
2049
2050impl<A, B> PartialEq<[B]> for ThinVec<A>
2051where
2052 A: PartialEq<B>,
2053{
2054 #[inline]
2055 fn eq(&self, other: &[B]) -> bool {
2056 self[..] == other[..]
2057 }
2058}
2059
2060impl<'a, A, B> PartialEq<&'a [B]> for ThinVec<A>
2061where
2062 A: PartialEq<B>,
2063{
2064 #[inline]
2065 fn eq(&self, other: &&'a [B]) -> bool {
2066 self[..] == other[..]
2067 }
2068}
2069
2070// Serde impls based on
2071// https://github.com/bluss/arrayvec/blob/67ec907a98c0f40c4b76066fed3c1af59d35cf6a/src/arrayvec.rs#L1222-L1267
2072#[cfg(feature = "serde")]
2073impl<T: serde::Serialize> serde::Serialize for ThinVec<T> {
2074 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2075 where
2076 S: serde::Serializer,
2077 {
2078 serializer.collect_seq(self.as_slice())
2079 }
2080}
2081
2082#[cfg(feature = "serde")]
2083impl<'de, T: serde::Deserialize<'de>> serde::Deserialize<'de> for ThinVec<T> {
2084 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2085 where
2086 D: serde::Deserializer<'de>,
2087 {
2088 use serde::de::{SeqAccess, Visitor};
2089 use serde::Deserialize;
2090
2091 struct ThinVecVisitor<T>(PhantomData<T>);
2092
2093 impl<'de, T: Deserialize<'de>> Visitor<'de> for ThinVecVisitor<T> {
2094 type Value = ThinVec<T>;
2095
2096 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2097 write!(formatter, "a sequence")
2098 }
2099
2100 fn visit_seq<SA>(self, mut seq: SA) -> Result<Self::Value, SA::Error>
2101 where
2102 SA: SeqAccess<'de>,
2103 {
2104 // Same policy as
2105 // https://github.com/serde-rs/serde/blob/ce0844b9ecc32377b5e4545d759d385a8c46bc6a/serde/src/private/size_hint.rs#L13
2106 let initial_capacity = seq.size_hint().unwrap_or_default().min(4096);
2107 let mut values = ThinVec::<T>::with_capacity(initial_capacity);
2108
2109 while let Some(value) = seq.next_element()? {
2110 values.push(value);
2111 }
2112
2113 Ok(values)
2114 }
2115 }
2116
2117 deserializer.deserialize_seq(ThinVecVisitor::<T>(PhantomData))
2118 }
2119}
2120
2121#[cfg(feature = "malloc_size_of")]
2122impl<T> MallocShallowSizeOf for ThinVec<T> {
2123 fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
2124 if self.capacity() == 0 {
2125 // If it's the singleton we might not be a heap pointer.
2126 return 0;
2127 }
2128
2129 assert_eq!(
2130 std::mem::size_of::<Self>(),
2131 std::mem::size_of::<*const ()>()
2132 );
2133 unsafe { ops.malloc_size_of(*(self as *const Self as *const *const ())) }
2134 }
2135}
2136
2137#[cfg(feature = "malloc_size_of")]
2138impl<T: MallocSizeOf> MallocSizeOf for ThinVec<T> {
2139 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
2140 let mut n = self.shallow_size_of(ops);
2141 for elem in self.iter() {
2142 n += elem.size_of(ops);
2143 }
2144 n
2145 }
2146}
2147
2148macro_rules! array_impls {
2149 ($($N:expr)*) => {$(
2150 impl<A, B> PartialEq<[B; $N]> for ThinVec<A> where A: PartialEq<B> {
2151 #[inline]
2152 fn eq(&self, other: &[B; $N]) -> bool { self[..] == other[..] }
2153 }
2154
2155 impl<'a, A, B> PartialEq<&'a [B; $N]> for ThinVec<A> where A: PartialEq<B> {
2156 #[inline]
2157 fn eq(&self, other: &&'a [B; $N]) -> bool { self[..] == other[..] }
2158 }
2159 )*}
2160}
2161
2162array_impls! {
2163 0 1 2 3 4 5 6 7 8 9
2164 10 11 12 13 14 15 16 17 18 19
2165 20 21 22 23 24 25 26 27 28 29
2166 30 31 32
2167}
2168
2169impl<T> Eq for ThinVec<T> where T: Eq {}
2170
2171impl<T> IntoIterator for ThinVec<T> {
2172 type Item = T;
2173 type IntoIter = IntoIter<T>;
2174
2175 fn into_iter(self) -> IntoIter<T> {
2176 IntoIter {
2177 vec: self,
2178 start: 0,
2179 }
2180 }
2181}
2182
2183impl<'a, T> IntoIterator for &'a ThinVec<T> {
2184 type Item = &'a T;
2185 type IntoIter = slice::Iter<'a, T>;
2186
2187 fn into_iter(self) -> slice::Iter<'a, T> {
2188 self.iter()
2189 }
2190}
2191
2192impl<'a, T> IntoIterator for &'a mut ThinVec<T> {
2193 type Item = &'a mut T;
2194 type IntoIter = slice::IterMut<'a, T>;
2195
2196 fn into_iter(self) -> slice::IterMut<'a, T> {
2197 self.iter_mut()
2198 }
2199}
2200
2201impl<T> Clone for ThinVec<T>
2202where
2203 T: Clone,
2204{
2205 #[inline]
2206 fn clone(&self) -> ThinVec<T> {
2207 #[cold]
2208 #[inline(never)]
2209 fn clone_non_singleton<T: Clone>(this: &ThinVec<T>) -> ThinVec<T> {
2210 let len = this.len();
2211 let mut new_vec = ThinVec::<T>::with_capacity(len);
2212 let mut data_raw = new_vec.data_raw();
2213 for x in this.iter() {
2214 unsafe {
2215 ptr::write(data_raw, x.clone());
2216 data_raw = data_raw.add(1);
2217 }
2218 }
2219 unsafe {
2220 // `this` is not the singleton, but `new_vec` will be if
2221 // `this` is empty.
2222 new_vec.set_len(len); // could be the singleton
2223 }
2224 new_vec
2225 }
2226
2227 if self.is_singleton() {
2228 ThinVec::new()
2229 } else {
2230 clone_non_singleton(self)
2231 }
2232 }
2233}
2234
2235impl<T> Default for ThinVec<T> {
2236 fn default() -> ThinVec<T> {
2237 ThinVec::new()
2238 }
2239}
2240
2241impl<T> FromIterator<T> for ThinVec<T> {
2242 #[inline]
2243 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> ThinVec<T> {
2244 let mut vec = ThinVec::new();
2245 vec.extend(iter);
2246 vec
2247 }
2248}
2249
2250impl<T: Clone> From<&[T]> for ThinVec<T> {
2251 /// Allocate a `ThinVec<T>` and fill it by cloning `s`'s items.
2252 ///
2253 /// # Examples
2254 ///
2255 /// ```
2256 /// use thin_vec::{ThinVec, thin_vec};
2257 ///
2258 /// assert_eq!(ThinVec::from(&[1, 2, 3][..]), thin_vec![1, 2, 3]);
2259 /// ```
2260 fn from(s: &[T]) -> ThinVec<T> {
2261 s.iter().cloned().collect()
2262 }
2263}
2264
2265impl<T: Clone> From<&mut [T]> for ThinVec<T> {
2266 /// Allocate a `ThinVec<T>` and fill it by cloning `s`'s items.
2267 ///
2268 /// # Examples
2269 ///
2270 /// ```
2271 /// use thin_vec::{ThinVec, thin_vec};
2272 ///
2273 /// assert_eq!(ThinVec::from(&mut [1, 2, 3][..]), thin_vec![1, 2, 3]);
2274 /// ```
2275 fn from(s: &mut [T]) -> ThinVec<T> {
2276 s.iter().cloned().collect()
2277 }
2278}
2279
2280impl<T, const N: usize> From<[T; N]> for ThinVec<T> {
2281 /// Allocate a `ThinVec<T>` and move `s`'s items into it.
2282 ///
2283 /// # Examples
2284 ///
2285 /// ```
2286 /// use thin_vec::{ThinVec, thin_vec};
2287 ///
2288 /// assert_eq!(ThinVec::from([1, 2, 3]), thin_vec![1, 2, 3]);
2289 /// ```
2290 fn from(s: [T; N]) -> ThinVec<T> {
2291 core::iter::IntoIterator::into_iter(s).collect()
2292 }
2293}
2294
2295impl<T> From<Box<[T]>> for ThinVec<T> {
2296 /// Convert a boxed slice into a vector by transferring ownership of
2297 /// the existing heap allocation.
2298 ///
2299 /// **NOTE:** unlike `std`, this must reallocate to change the layout!
2300 ///
2301 /// # Examples
2302 ///
2303 /// ```
2304 /// use thin_vec::{ThinVec, thin_vec};
2305 ///
2306 /// let b: Box<[i32]> = thin_vec![1, 2, 3].into_iter().collect();
2307 /// assert_eq!(ThinVec::from(b), thin_vec![1, 2, 3]);
2308 /// ```
2309 fn from(s: Box<[T]>) -> Self {
2310 // Can just lean on the fact that `Box<[T]>` -> `Vec<T>` is Free.
2311 Vec::from(s).into_iter().collect()
2312 }
2313}
2314
2315impl<T> From<Vec<T>> for ThinVec<T> {
2316 /// Convert a `std::Vec` into a `ThinVec`.
2317 ///
2318 /// **NOTE:** this must reallocate to change the layout!
2319 ///
2320 /// # Examples
2321 ///
2322 /// ```
2323 /// use thin_vec::{ThinVec, thin_vec};
2324 ///
2325 /// let b: Vec<i32> = vec![1, 2, 3];
2326 /// assert_eq!(ThinVec::from(b), thin_vec![1, 2, 3]);
2327 /// ```
2328 fn from(s: Vec<T>) -> Self {
2329 s.into_iter().collect()
2330 }
2331}
2332
2333impl<T> From<ThinVec<T>> for Vec<T> {
2334 /// Convert a `ThinVec` into a `std::Vec`.
2335 ///
2336 /// **NOTE:** this must reallocate to change the layout!
2337 ///
2338 /// # Examples
2339 ///
2340 /// ```
2341 /// use thin_vec::{ThinVec, thin_vec};
2342 ///
2343 /// let b: ThinVec<i32> = thin_vec![1, 2, 3];
2344 /// assert_eq!(Vec::from(b), vec![1, 2, 3]);
2345 /// ```
2346 fn from(s: ThinVec<T>) -> Self {
2347 s.into_iter().collect()
2348 }
2349}
2350
2351impl<T> From<ThinVec<T>> for Box<[T]> {
2352 /// Convert a vector into a boxed slice.
2353 ///
2354 /// If `v` has excess capacity, its items will be moved into a
2355 /// newly-allocated buffer with exactly the right capacity.
2356 ///
2357 /// **NOTE:** unlike `std`, this must reallocate to change the layout!
2358 ///
2359 /// # Examples
2360 ///
2361 /// ```
2362 /// use thin_vec::{ThinVec, thin_vec};
2363 /// assert_eq!(Box::from(thin_vec![1, 2, 3]), thin_vec![1, 2, 3].into_iter().collect());
2364 /// ```
2365 fn from(v: ThinVec<T>) -> Self {
2366 v.into_iter().collect()
2367 }
2368}
2369
2370impl From<&str> for ThinVec<u8> {
2371 /// Allocate a `ThinVec<u8>` and fill it with a UTF-8 string.
2372 ///
2373 /// # Examples
2374 ///
2375 /// ```
2376 /// use thin_vec::{ThinVec, thin_vec};
2377 ///
2378 /// assert_eq!(ThinVec::from("123"), thin_vec![b'1', b'2', b'3']);
2379 /// ```
2380 fn from(s: &str) -> ThinVec<u8> {
2381 From::from(s.as_bytes())
2382 }
2383}
2384
2385impl<T, const N: usize> TryFrom<ThinVec<T>> for [T; N] {
2386 type Error = ThinVec<T>;
2387
2388 /// Gets the entire contents of the `ThinVec<T>` as an array,
2389 /// if its size exactly matches that of the requested array.
2390 ///
2391 /// # Examples
2392 ///
2393 /// ```
2394 /// use thin_vec::{ThinVec, thin_vec};
2395 /// use std::convert::TryInto;
2396 ///
2397 /// assert_eq!(thin_vec![1, 2, 3].try_into(), Ok([1, 2, 3]));
2398 /// assert_eq!(<ThinVec<i32>>::new().try_into(), Ok([]));
2399 /// ```
2400 ///
2401 /// If the length doesn't match, the input comes back in `Err`:
2402 /// ```
2403 /// use thin_vec::{ThinVec, thin_vec};
2404 /// use std::convert::TryInto;
2405 ///
2406 /// let r: Result<[i32; 4], _> = (0..10).collect::<ThinVec<_>>().try_into();
2407 /// assert_eq!(r, Err(thin_vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
2408 /// ```
2409 ///
2410 /// If you're fine with just getting a prefix of the `ThinVec<T>`,
2411 /// you can call [`.truncate(N)`](ThinVec::truncate) first.
2412 /// ```
2413 /// use thin_vec::{ThinVec, thin_vec};
2414 /// use std::convert::TryInto;
2415 ///
2416 /// let mut v = ThinVec::from("hello world");
2417 /// v.sort();
2418 /// v.truncate(2);
2419 /// let [a, b]: [_; 2] = v.try_into().unwrap();
2420 /// assert_eq!(a, b' ');
2421 /// assert_eq!(b, b'd');
2422 /// ```
2423 fn try_from(mut vec: ThinVec<T>) -> Result<[T; N], ThinVec<T>> {
2424 if vec.len() != N {
2425 return Err(vec);
2426 }
2427
2428 // SAFETY: `.set_len(0)` is always sound.
2429 unsafe { vec.set_len(0) };
2430
2431 // SAFETY: A `ThinVec`'s pointer is always aligned properly, and
2432 // the alignment the array needs is the same as the items.
2433 // We checked earlier that we have sufficient items.
2434 // The items will not double-drop as the `set_len`
2435 // tells the `ThinVec` not to also drop them.
2436 let array = unsafe { ptr::read(vec.data_raw() as *const [T; N]) };
2437 Ok(array)
2438 }
2439}
2440
2441/// An iterator that moves out of a vector.
2442///
2443/// This `struct` is created by the [`ThinVec::into_iter`][]
2444/// (provided by the [`IntoIterator`] trait).
2445///
2446/// # Example
2447///
2448/// ```
2449/// use thin_vec::thin_vec;
2450///
2451/// let v = thin_vec![0, 1, 2];
2452/// let iter: thin_vec::IntoIter<_> = v.into_iter();
2453/// ```
2454pub struct IntoIter<T> {
2455 vec: ThinVec<T>,
2456 start: usize,
2457}
2458
2459impl<T> IntoIter<T> {
2460 /// Returns the remaining items of this iterator as a slice.
2461 ///
2462 /// # Examples
2463 ///
2464 /// ```
2465 /// use thin_vec::thin_vec;
2466 ///
2467 /// let vec = thin_vec!['a', 'b', 'c'];
2468 /// let mut into_iter = vec.into_iter();
2469 /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
2470 /// let _ = into_iter.next().unwrap();
2471 /// assert_eq!(into_iter.as_slice(), &['b', 'c']);
2472 /// ```
2473 pub fn as_slice(&self) -> &[T] {
2474 unsafe { slice::from_raw_parts(self.vec.data_raw().add(self.start), self.len()) }
2475 }
2476
2477 /// Returns the remaining items of this iterator as a mutable slice.
2478 ///
2479 /// # Examples
2480 ///
2481 /// ```
2482 /// use thin_vec::thin_vec;
2483 ///
2484 /// let vec = thin_vec!['a', 'b', 'c'];
2485 /// let mut into_iter = vec.into_iter();
2486 /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
2487 /// into_iter.as_mut_slice()[2] = 'z';
2488 /// assert_eq!(into_iter.next().unwrap(), 'a');
2489 /// assert_eq!(into_iter.next().unwrap(), 'b');
2490 /// assert_eq!(into_iter.next().unwrap(), 'z');
2491 /// ```
2492 pub fn as_mut_slice(&mut self) -> &mut [T] {
2493 unsafe { &mut *self.as_raw_mut_slice() }
2494 }
2495
2496 fn as_raw_mut_slice(&mut self) -> *mut [T] {
2497 unsafe { ptr::slice_from_raw_parts_mut(self.vec.data_raw().add(self.start), self.len()) }
2498 }
2499}
2500
2501impl<T> Iterator for IntoIter<T> {
2502 type Item = T;
2503 fn next(&mut self) -> Option<T> {
2504 if self.start == self.vec.len() {
2505 None
2506 } else {
2507 unsafe {
2508 let old_start = self.start;
2509 self.start += 1;
2510 Some(ptr::read(self.vec.data_raw().add(old_start)))
2511 }
2512 }
2513 }
2514
2515 fn size_hint(&self) -> (usize, Option<usize>) {
2516 let len = self.vec.len() - self.start;
2517 (len, Some(len))
2518 }
2519}
2520
2521impl<T> DoubleEndedIterator for IntoIter<T> {
2522 fn next_back(&mut self) -> Option<T> {
2523 if self.start == self.vec.len() {
2524 None
2525 } else {
2526 self.vec.pop()
2527 }
2528 }
2529}
2530
2531impl<T> ExactSizeIterator for IntoIter<T> {}
2532
2533impl<T> core::iter::FusedIterator for IntoIter<T> {}
2534
2535// SAFETY: the length calculation is trivial, we're an array! And if it's wrong we're So Screwed.
2536#[cfg(feature = "unstable")]
2537unsafe impl<T> core::iter::TrustedLen for IntoIter<T> {}
2538
2539impl<T> Drop for IntoIter<T> {
2540 #[inline]
2541 fn drop(&mut self) {
2542 #[cold]
2543 #[inline(never)]
2544 fn drop_non_singleton<T>(this: &mut IntoIter<T>) {
2545 unsafe {
2546 let mut vec = mem::replace(&mut this.vec, ThinVec::new());
2547 ptr::drop_in_place(&mut vec[this.start..]);
2548 vec.set_len_non_singleton(0)
2549 }
2550 }
2551
2552 if !self.vec.is_singleton() {
2553 drop_non_singleton(self);
2554 }
2555 }
2556}
2557
2558impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
2559 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2560 f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
2561 }
2562}
2563
2564impl<T> AsRef<[T]> for IntoIter<T> {
2565 fn as_ref(&self) -> &[T] {
2566 self.as_slice()
2567 }
2568}
2569
2570impl<T: Clone> Clone for IntoIter<T> {
2571 #[allow(clippy::into_iter_on_ref)]
2572 fn clone(&self) -> Self {
2573 // Just create a new `ThinVec` from the remaining elements and IntoIter it
2574 self.as_slice()
2575 .into_iter()
2576 .cloned()
2577 .collect::<ThinVec<_>>()
2578 .into_iter()
2579 }
2580}
2581
2582/// A draining iterator for `ThinVec<T>`.
2583///
2584/// This `struct` is created by [`ThinVec::drain`].
2585/// See its documentation for more.
2586///
2587/// # Example
2588///
2589/// ```
2590/// use thin_vec::thin_vec;
2591///
2592/// let mut v = thin_vec![0, 1, 2];
2593/// let iter: thin_vec::Drain<_> = v.drain(..);
2594/// ```
2595pub struct Drain<'a, T> {
2596 // Ok so ThinVec::drain takes a range of the ThinVec and yields the contents by-value,
2597 // then backshifts the array. During iteration the array is in an unsound state
2598 // (big deinitialized hole in it), and this is very dangerous.
2599 //
2600 // Our first line of defense is the borrow checker: we have a mutable borrow, so nothing
2601 // can access the ThinVec while we exist. As long as we make sure the ThinVec is in a valid
2602 // state again before we release the borrow, everything should be A-OK! We do this cleanup
2603 // in our Drop impl.
2604 //
2605 // Unfortunately, that's unsound, because mem::forget exists and The Leakpocalypse Is Real.
2606 // So we can't actually guarantee our destructor runs before our borrow expires. Thankfully
2607 // this isn't fatal: we can just set the ThinVec's len to 0 at the start, so if anyone
2608 // leaks the Drain, we just leak everything the ThinVec contained out of spite! If they
2609 // *don't* leak us then we can properly repair the len in our Drop impl. This is known
2610 // as "leak amplification", and is the same approach std uses.
2611 //
2612 // But we can do slightly better than setting the len to 0! The drain breaks us up into
2613 // these parts:
2614 //
2615 // ```text
2616 //
2617 // [A, B, C, D, E, F, G, H, _, _]
2618 // ____ __________ ____ ____
2619 // | | | |
2620 // prefix drain tail spare-cap
2621 // ```
2622 //
2623 // As the drain iterator is consumed from both ends (DoubleEnded!), we'll start to look
2624 // like this:
2625 //
2626 // ```text
2627 // [A, B, _, _, E, _, G, H, _, _]
2628 // ____ __________ ____ ____
2629 // | | | |
2630 // prefix drain tail spare-cap
2631 // ```
2632 //
2633 // Note that the prefix is always valid and untouched, as such we can set the len
2634 // to the prefix when doing leak-amplification. As a bonus, we can use this value
2635 // to remember where the drain range starts. At the end we'll look like this
2636 // (we exhaust ourselves in our Drop impl):
2637 //
2638 // ```text
2639 // [A, B, _, _, _, _, G, H, _, _]
2640 // _____ __________ _____ ____
2641 // | | | |
2642 // len drain tail spare-cap
2643 // ```
2644 //
2645 // And need to become this:
2646 //
2647 // ```text
2648 // [A, B, G, H, _, _, _, _, _, _]
2649 // ___________ ________________
2650 // | |
2651 // len spare-cap
2652 // ```
2653 //
2654 // All this requires is moving the tail back to the prefix (stored in `len`)
2655 // and setting `len` to `len + tail_len` to undo the leak amplification.
2656 /// An iterator over the elements we're removing.
2657 ///
2658 /// As we go we'll be `read`ing out of the shared refs yielded by this.
2659 /// It's ok to use Iter here because it promises to only take refs to the parts
2660 /// we haven't yielded yet.
2661 iter: Iter<'a, T>,
2662 /// The actual ThinVec, which we need to hold onto to undo the leak amplification
2663 /// and backshift the tail into place. This should only be accessed when we're
2664 /// completely done with the Iter in the `drop` impl of this type (or miri will get mad).
2665 ///
2666 /// Since we set the `len` of this to be before `Iter`, we can use that `len`
2667 /// to retrieve the index of the start of the drain range later.
2668 vec: NonNull<ThinVec<T>>,
2669 /// The one-past-the-end index of the drain range, or equivalently the start of the tail.
2670 end: usize,
2671 /// The length of the tail.
2672 tail: usize,
2673}
2674
2675impl<'a, T> Iterator for Drain<'a, T> {
2676 type Item = T;
2677 fn next(&mut self) -> Option<T> {
2678 self.iter.next().map(|x| unsafe { ptr::read(x) })
2679 }
2680
2681 fn size_hint(&self) -> (usize, Option<usize>) {
2682 self.iter.size_hint()
2683 }
2684}
2685
2686impl<'a, T> DoubleEndedIterator for Drain<'a, T> {
2687 fn next_back(&mut self) -> Option<T> {
2688 self.iter.next_back().map(|x| unsafe { ptr::read(x) })
2689 }
2690}
2691
2692impl<'a, T> ExactSizeIterator for Drain<'a, T> {}
2693
2694// SAFETY: we need to keep track of this perfectly Or Else anyway!
2695#[cfg(feature = "unstable")]
2696unsafe impl<T> core::iter::TrustedLen for Drain<'_, T> {}
2697
2698impl<T> core::iter::FusedIterator for Drain<'_, T> {}
2699
2700impl<'a, T> Drop for Drain<'a, T> {
2701 fn drop(&mut self) {
2702 // Consume the rest of the iterator.
2703 for _ in self.by_ref() {}
2704
2705 // Move the tail over the drained items, and update the length.
2706 unsafe {
2707 let vec = self.vec.as_mut();
2708
2709 // Don't mutate the empty singleton!
2710 if !vec.is_singleton() {
2711 let old_len = vec.len();
2712 let start = vec.data_raw().add(old_len);
2713 let end = vec.data_raw().add(self.end);
2714 ptr::copy(end, start, self.tail);
2715 vec.set_len_non_singleton(old_len + self.tail);
2716 }
2717 }
2718 }
2719}
2720
2721impl<T: fmt::Debug> fmt::Debug for Drain<'_, T> {
2722 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2723 f.debug_tuple("Drain").field(&self.iter.as_slice()).finish()
2724 }
2725}
2726
2727impl<'a, T> Drain<'a, T> {
2728 /// Returns the remaining items of this iterator as a slice.
2729 ///
2730 /// # Examples
2731 ///
2732 /// ```
2733 /// use thin_vec::thin_vec;
2734 ///
2735 /// let mut vec = thin_vec!['a', 'b', 'c'];
2736 /// let mut drain = vec.drain(..);
2737 /// assert_eq!(drain.as_slice(), &['a', 'b', 'c']);
2738 /// let _ = drain.next().unwrap();
2739 /// assert_eq!(drain.as_slice(), &['b', 'c']);
2740 /// ```
2741 #[must_use]
2742 pub fn as_slice(&self) -> &[T] {
2743 // SAFETY: this is A-OK because the elements that the underlying
2744 // iterator still points at are still logically initialized and contiguous.
2745 self.iter.as_slice()
2746 }
2747}
2748
2749impl<'a, T> AsRef<[T]> for Drain<'a, T> {
2750 fn as_ref(&self) -> &[T] {
2751 self.as_slice()
2752 }
2753}
2754
2755/// A splicing iterator for `ThinVec`.
2756///
2757/// This struct is created by [`ThinVec::splice`][].
2758/// See its documentation for more.
2759///
2760/// # Example
2761///
2762/// ```
2763/// use thin_vec::thin_vec;
2764///
2765/// let mut v = thin_vec![0, 1, 2];
2766/// let new = [7, 8];
2767/// let iter: thin_vec::Splice<_> = v.splice(1.., new);
2768/// ```
2769#[derive(Debug)]
2770pub struct Splice<'a, I: Iterator + 'a> {
2771 drain: Drain<'a, I::Item>,
2772 replace_with: I,
2773}
2774
2775impl<I: Iterator> Iterator for Splice<'_, I> {
2776 type Item = I::Item;
2777
2778 fn next(&mut self) -> Option<Self::Item> {
2779 self.drain.next()
2780 }
2781
2782 fn size_hint(&self) -> (usize, Option<usize>) {
2783 self.drain.size_hint()
2784 }
2785}
2786
2787impl<I: Iterator> DoubleEndedIterator for Splice<'_, I> {
2788 fn next_back(&mut self) -> Option<Self::Item> {
2789 self.drain.next_back()
2790 }
2791}
2792
2793impl<I: Iterator> ExactSizeIterator for Splice<'_, I> {}
2794
2795impl<I: Iterator> Drop for Splice<'_, I> {
2796 fn drop(&mut self) {
2797 // Ensure we've fully drained out the range
2798 self.drain.by_ref().for_each(drop);
2799
2800 unsafe {
2801 // If there's no tail elements, then the inner ThinVec is already
2802 // correct and we can just extend it like normal.
2803 if self.drain.tail == 0 {
2804 self.drain.vec.as_mut().extend(self.replace_with.by_ref());
2805 return;
2806 }
2807
2808 // First fill the range left by drain().
2809 if !self.drain.fill(&mut self.replace_with) {
2810 return;
2811 }
2812
2813 // There may be more elements. Use the lower bound as an estimate.
2814 let (lower_bound, _upper_bound) = self.replace_with.size_hint();
2815 if lower_bound > 0 {
2816 self.drain.move_tail(lower_bound);
2817 if !self.drain.fill(&mut self.replace_with) {
2818 return;
2819 }
2820 }
2821
2822 // Collect any remaining elements.
2823 // This is a zero-length vector which does not allocate if `lower_bound` was exact.
2824 let mut collected = self
2825 .replace_with
2826 .by_ref()
2827 .collect::<Vec<I::Item>>()
2828 .into_iter();
2829 // Now we have an exact count.
2830 if collected.len() > 0 {
2831 self.drain.move_tail(collected.len());
2832 let filled = self.drain.fill(&mut collected);
2833 debug_assert!(filled);
2834 debug_assert_eq!(collected.len(), 0);
2835 }
2836 }
2837 // Let `Drain::drop` move the tail back if necessary and restore `vec.len`.
2838 }
2839}
2840
2841#[cfg(feature = "gecko-ffi")]
2842#[repr(C, align(8))]
2843struct AutoBuffer<T, const N: usize> {
2844 header: Header,
2845 buffer: mem::MaybeUninit<[T; N]>,
2846}
2847
2848#[doc(hidden)]
2849#[cfg(feature = "gecko-ffi")]
2850#[repr(C)]
2851pub struct AutoThinVec<T, const N: usize> {
2852 inner: ThinVec<T>,
2853 buffer: AutoBuffer<T, N>,
2854 _pinned: std::marker::PhantomPinned,
2855}
2856
2857#[cfg(feature = "gecko-ffi")]
2858impl<T, const N: usize> AutoThinVec<T, N> {
2859 /// Implementation detail for the auto_thin_vec macro.
2860 #[inline]
2861 #[doc(hidden)]
2862 pub fn new_unpinned() -> Self {
2863 // This condition is hard-coded in nsTArray.h
2864 assert!(
2865 std::mem::align_of::<T>() <= 8,
2866 "Can't handle alignments greater than 8"
2867 );
2868 assert_eq!(std::mem::offset_of!(Self, buffer), AUTO_ARRAY_HEADER_OFFSET);
2869 Self {
2870 inner: ThinVec::new(),
2871 buffer: AutoBuffer {
2872 header: Header {
2873 _len: 0,
2874 _cap: pack_capacity_and_auto(N as SizeType, true),
2875 },
2876 buffer: mem::MaybeUninit::uninit(),
2877 },
2878 _pinned: std::marker::PhantomPinned,
2879 }
2880 }
2881
2882 /// Returns a raw pointer to the inner ThinVec. Note that if you dereference it from rust, you
2883 /// need to make sure not to move the ThinVec manually via something like
2884 /// `std::mem::take(&mut auto_vec)`.
2885 pub fn as_mut_ptr(self: std::pin::Pin<&mut Self>) -> *mut ThinVec<T> {
2886 debug_assert!(self.is_auto_array());
2887 unsafe { &mut self.get_unchecked_mut().inner }
2888 }
2889
2890 #[inline]
2891 pub unsafe fn shrink_to_fit_known_singleton(self: std::pin::Pin<&mut Self>) {
2892 debug_assert!(self.is_singleton());
2893 let this = unsafe { self.get_unchecked_mut() };
2894 this.buffer.header.set_len(0);
2895 // TODO(emilio): Use NonNull::from_mut when msrv allows.
2896 this.inner.ptr = NonNull::new_unchecked(&mut this.buffer.header);
2897 debug_assert!(this.inner.is_auto_array());
2898 debug_assert!(this.inner.uses_stack_allocated_buffer());
2899 }
2900
2901 pub fn shrink_to_fit(self: std::pin::Pin<&mut Self>) {
2902 let this = unsafe { self.get_unchecked_mut() };
2903 this.inner.shrink_to_fit();
2904 debug_assert!(this.inner.is_auto_array());
2905 }
2906}
2907
2908// NOTE(emilio): DerefMut wouldn't be safe, see the comment in as_mut_ptr.
2909#[cfg(feature = "gecko-ffi")]
2910impl<T, const N: usize> Deref for AutoThinVec<T, N> {
2911 type Target = ThinVec<T>;
2912
2913 fn deref(&self) -> &Self::Target {
2914 &self.inner
2915 }
2916}
2917
2918/// Create a ThinVec<$ty> named `$name`, with capacity for `$cap` inline elements.
2919///
2920/// TODO(emilio): This would be a lot more convenient to use with super let, see
2921/// <https://github.com/rust-lang/rust/issues/139076>
2922#[cfg(feature = "gecko-ffi")]
2923#[macro_export]
2924macro_rules! auto_thin_vec {
2925 (let $name:ident : [$ty:ty; $cap:literal]) => {
2926 let auto_vec = $crate::AutoThinVec::<$ty, $cap>::new_unpinned();
2927 let mut $name = core::pin::pin!(auto_vec);
2928 unsafe { $name.as_mut().shrink_to_fit_known_singleton() };
2929 };
2930}
2931
2932/// Private helper methods for `Splice::drop`
2933impl<T> Drain<'_, T> {
2934 /// The range from `self.vec.len` to `self.tail_start` contains elements
2935 /// that have been moved out.
2936 /// Fill that range as much as possible with new elements from the `replace_with` iterator.
2937 /// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.)
2938 unsafe fn fill<I: Iterator<Item = T>>(&mut self, replace_with: &mut I) -> bool {
2939 let vec = unsafe { self.vec.as_mut() };
2940 let range_start = vec.len();
2941 let range_end = self.end;
2942 let range_slice = unsafe {
2943 slice::from_raw_parts_mut(vec.data_raw().add(range_start), range_end - range_start)
2944 };
2945
2946 for place in range_slice {
2947 if let Some(new_item) = replace_with.next() {
2948 unsafe { ptr::write(place, new_item) };
2949 vec.set_len(vec.len() + 1);
2950 } else {
2951 return false;
2952 }
2953 }
2954 true
2955 }
2956
2957 /// Makes room for inserting more elements before the tail.
2958 unsafe fn move_tail(&mut self, additional: usize) {
2959 let vec = unsafe { self.vec.as_mut() };
2960 let len = self.end + self.tail;
2961 vec.reserve(len.checked_add(additional).unwrap_cap_overflow());
2962
2963 let new_tail_start = self.end + additional;
2964 unsafe {
2965 let src = vec.data_raw().add(self.end);
2966 let dst = vec.data_raw().add(new_tail_start);
2967 ptr::copy(src, dst, self.tail);
2968 }
2969 self.end = new_tail_start;
2970 }
2971}
2972
2973/// An iterator for [`ThinVec`] which uses a closure to determine if an element should be removed.
2974#[must_use = "iterators are lazy and do nothing unless consumed"]
2975pub struct ExtractIf<'a, T, F> {
2976 vec: &'a mut ThinVec<T>,
2977 /// The index of the item that will be inspected by the next call to `next`.
2978 idx: usize,
2979 /// Elements at and beyond this point will be retained. Must be equal or smaller than `old_len`.
2980 end: usize,
2981 /// The number of items that have been drained (removed) thus far.
2982 del: usize,
2983 /// The original length of `vec` prior to draining.
2984 old_len: usize,
2985 /// The filter test predicate.
2986 pred: F,
2987}
2988
2989impl<T, F> Iterator for ExtractIf<'_, T, F>
2990where
2991 F: FnMut(&mut T) -> bool,
2992{
2993 type Item = T;
2994
2995 fn next(&mut self) -> Option<T> {
2996 unsafe {
2997 let v = self.vec.data_raw();
2998 while self.idx < self.end {
2999 let i = self.idx;
3000 let drained = (self.pred)(&mut *v.add(i));
3001 // Update the index *after* the predicate is called. If the index
3002 // is updated prior and the predicate panics, the element at this
3003 // index would be leaked.
3004 self.idx += 1;
3005 if drained {
3006 self.del += 1;
3007 return Some(ptr::read(v.add(i)));
3008 } else if self.del > 0 {
3009 let del = self.del;
3010 let src: *const T = v.add(i);
3011 let dst: *mut T = v.add(i - del);
3012 ptr::copy_nonoverlapping(src, dst, 1);
3013 }
3014 }
3015 None
3016 }
3017 }
3018
3019 fn size_hint(&self) -> (usize, Option<usize>) {
3020 (0, Some(self.end - self.idx))
3021 }
3022}
3023
3024impl<A, F> Drop for ExtractIf<'_, A, F> {
3025 fn drop(&mut self) {
3026 unsafe {
3027 if self.idx < self.old_len && self.del > 0 {
3028 // This is a pretty messed up state, and there isn't really an
3029 // obviously right thing to do. We don't want to keep trying
3030 // to execute `pred`, so we just backshift all the unprocessed
3031 // elements and tell the vec that they still exist. The backshift
3032 // is required to prevent a double-drop of the last successfully
3033 // drained item prior to a panic in the predicate.
3034 let ptr = self.vec.data_raw();
3035 let src = ptr.add(self.idx);
3036 let dst = src.sub(self.del);
3037 let tail_len = self.old_len - self.idx;
3038 src.copy_to(dst, tail_len);
3039 }
3040
3041 self.vec.set_len(self.old_len - self.del);
3042 }
3043 }
3044}
3045
3046/// Write is implemented for `ThinVec<u8>` by appending to the vector.
3047/// The vector will grow as needed.
3048/// This implementation is identical to the one for `Vec<u8>`.
3049#[cfg(feature = "std")]
3050impl std::io::Write for ThinVec<u8> {
3051 #[inline]
3052 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
3053 self.extend_from_slice(buf);
3054 Ok(buf.len())
3055 }
3056
3057 #[inline]
3058 fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
3059 self.extend_from_slice(buf);
3060 Ok(())
3061 }
3062
3063 #[inline]
3064 fn flush(&mut self) -> std::io::Result<()> {
3065 Ok(())
3066 }
3067}
3068
3069// TODO: a million Index impls
3070
3071#[cfg(test)]
3072mod tests {
3073 use super::{ThinVec, MAX_CAP};
3074 use crate::alloc::{string::ToString, vec};
3075
3076 #[test]
3077 fn test_size_of() {
3078 use core::mem::size_of;
3079 assert_eq!(size_of::<ThinVec<u8>>(), size_of::<&u8>());
3080
3081 assert_eq!(size_of::<Option<ThinVec<u8>>>(), size_of::<&u8>());
3082 }
3083
3084 #[test]
3085 fn test_drop_empty() {
3086 ThinVec::<u8>::new();
3087 }
3088
3089 #[test]
3090 fn test_data_ptr_alignment() {
3091 let v = ThinVec::<u16>::new();
3092 assert!(v.data_raw() as usize % core::mem::align_of::<u16>() == 0);
3093
3094 let v = ThinVec::<u32>::new();
3095 assert!(v.data_raw() as usize % core::mem::align_of::<u32>() == 0);
3096
3097 let v = ThinVec::<u64>::new();
3098 assert!(v.data_raw() as usize % core::mem::align_of::<u64>() == 0);
3099 }
3100
3101 #[test]
3102 #[cfg_attr(feature = "gecko-ffi", should_panic)]
3103 fn test_overaligned_type_is_rejected_for_gecko_ffi_mode() {
3104 #[repr(align(16))]
3105 struct Align16(u8);
3106
3107 let v = ThinVec::<Align16>::new();
3108 assert!(v.data_raw() as usize % 16 == 0);
3109 }
3110
3111 #[test]
3112 fn test_partial_eq() {
3113 assert_eq!(thin_vec![0], thin_vec![0]);
3114 assert_ne!(thin_vec![0], thin_vec![1]);
3115 assert_eq!(thin_vec![1, 2, 3], vec![1, 2, 3]);
3116 }
3117
3118 #[test]
3119 fn test_alloc() {
3120 let mut v = ThinVec::new();
3121 assert!(!v.has_allocation());
3122 v.push(1);
3123 assert!(v.has_allocation());
3124 v.pop();
3125 assert!(v.has_allocation());
3126 v.shrink_to_fit();
3127 assert!(!v.has_allocation());
3128 v.reserve(64);
3129 assert!(v.has_allocation());
3130 v = ThinVec::with_capacity(64);
3131 assert!(v.has_allocation());
3132 v = ThinVec::with_capacity(0);
3133 assert!(!v.has_allocation());
3134 }
3135
3136 #[test]
3137 fn test_drain_items() {
3138 let mut vec = thin_vec![1, 2, 3];
3139 let mut vec2 = thin_vec![];
3140 for i in vec.drain(..) {
3141 vec2.push(i);
3142 }
3143 assert_eq!(vec, []);
3144 assert_eq!(vec2, [1, 2, 3]);
3145 }
3146
3147 #[test]
3148 fn test_drain_items_reverse() {
3149 let mut vec = thin_vec![1, 2, 3];
3150 let mut vec2 = thin_vec![];
3151 for i in vec.drain(..).rev() {
3152 vec2.push(i);
3153 }
3154 assert_eq!(vec, []);
3155 assert_eq!(vec2, [3, 2, 1]);
3156 }
3157
3158 #[test]
3159 fn test_drain_items_zero_sized() {
3160 let mut vec = thin_vec![(), (), ()];
3161 let mut vec2 = thin_vec![];
3162 for i in vec.drain(..) {
3163 vec2.push(i);
3164 }
3165 assert_eq!(vec, []);
3166 assert_eq!(vec2, [(), (), ()]);
3167 }
3168
3169 #[test]
3170 #[should_panic]
3171 fn test_drain_out_of_bounds() {
3172 let mut v = thin_vec![1, 2, 3, 4, 5];
3173 v.drain(5..6);
3174 }
3175
3176 #[test]
3177 fn test_drain_range() {
3178 let mut v = thin_vec![1, 2, 3, 4, 5];
3179 for _ in v.drain(4..) {}
3180 assert_eq!(v, &[1, 2, 3, 4]);
3181
3182 let mut v: ThinVec<_> = (1..6).map(|x| x.to_string()).collect();
3183 for _ in v.drain(1..4) {}
3184 assert_eq!(v, &[1.to_string(), 5.to_string()]);
3185
3186 let mut v: ThinVec<_> = (1..6).map(|x| x.to_string()).collect();
3187 for _ in v.drain(1..4).rev() {}
3188 assert_eq!(v, &[1.to_string(), 5.to_string()]);
3189
3190 let mut v: ThinVec<_> = thin_vec![(); 5];
3191 for _ in v.drain(1..4).rev() {}
3192 assert_eq!(v, &[(), ()]);
3193 }
3194
3195 #[test]
3196 fn test_drain_max_vec_size() {
3197 let mut v = ThinVec::<()>::with_capacity(MAX_CAP);
3198 unsafe {
3199 v.set_len(MAX_CAP);
3200 }
3201 for _ in v.drain(MAX_CAP - 1..) {}
3202 assert_eq!(v.len(), MAX_CAP - 1);
3203 }
3204
3205 #[test]
3206 fn test_clear() {
3207 let mut v = ThinVec::<i32>::new();
3208 assert_eq!(v.len(), 0);
3209 assert_eq!(v.capacity(), 0);
3210 assert_eq!(&v[..], &[]);
3211
3212 v.clear();
3213 assert_eq!(v.len(), 0);
3214 assert_eq!(v.capacity(), 0);
3215 assert_eq!(&v[..], &[]);
3216
3217 v.push(1);
3218 v.push(2);
3219 assert_eq!(v.len(), 2);
3220 assert!(v.capacity() >= 2);
3221 assert_eq!(&v[..], &[1, 2]);
3222
3223 v.clear();
3224 assert_eq!(v.len(), 0);
3225 assert!(v.capacity() >= 2);
3226 assert_eq!(&v[..], &[]);
3227
3228 v.push(3);
3229 v.push(4);
3230 assert_eq!(v.len(), 2);
3231 assert!(v.capacity() >= 2);
3232 assert_eq!(&v[..], &[3, 4]);
3233
3234 v.clear();
3235 assert_eq!(v.len(), 0);
3236 assert!(v.capacity() >= 2);
3237 assert_eq!(&v[..], &[]);
3238
3239 v.clear();
3240 assert_eq!(v.len(), 0);
3241 assert!(v.capacity() >= 2);
3242 assert_eq!(&v[..], &[]);
3243 }
3244
3245 #[test]
3246 fn test_empty_singleton_torture() {
3247 {
3248 let mut v = ThinVec::<i32>::new();
3249 assert_eq!(v.len(), 0);
3250 assert_eq!(v.capacity(), 0);
3251 assert!(v.is_empty());
3252 assert_eq!(&v[..], &[]);
3253 assert_eq!(&mut v[..], &mut []);
3254
3255 assert_eq!(v.pop(), None);
3256 assert_eq!(v.len(), 0);
3257 assert_eq!(v.capacity(), 0);
3258 assert_eq!(&v[..], &[]);
3259 }
3260
3261 {
3262 let v = ThinVec::<i32>::new();
3263 assert_eq!(v.into_iter().count(), 0);
3264
3265 let v = ThinVec::<i32>::new();
3266 #[allow(clippy::never_loop)]
3267 for _ in v.into_iter() {
3268 unreachable!();
3269 }
3270 }
3271
3272 {
3273 let mut v = ThinVec::<i32>::new();
3274 assert_eq!(v.drain(..).len(), 0);
3275
3276 #[allow(clippy::never_loop)]
3277 for _ in v.drain(..) {
3278 unreachable!()
3279 }
3280
3281 assert_eq!(v.len(), 0);
3282 assert_eq!(v.capacity(), 0);
3283 assert_eq!(&v[..], &[]);
3284 }
3285
3286 {
3287 let mut v = ThinVec::<i32>::new();
3288 assert_eq!(v.splice(.., []).len(), 0);
3289
3290 #[allow(clippy::never_loop)]
3291 for _ in v.splice(.., []) {
3292 unreachable!()
3293 }
3294
3295 assert_eq!(v.len(), 0);
3296 assert_eq!(v.capacity(), 0);
3297 assert_eq!(&v[..], &[]);
3298 }
3299
3300 {
3301 let mut v = ThinVec::<i32>::new();
3302 v.truncate(1);
3303 assert_eq!(v.len(), 0);
3304 assert_eq!(v.capacity(), 0);
3305 assert_eq!(&v[..], &[]);
3306
3307 v.truncate(0);
3308 assert_eq!(v.len(), 0);
3309 assert_eq!(v.capacity(), 0);
3310 assert_eq!(&v[..], &[]);
3311 }
3312
3313 {
3314 let mut v = ThinVec::<i32>::new();
3315 v.shrink_to_fit();
3316 assert_eq!(v.len(), 0);
3317 assert_eq!(v.capacity(), 0);
3318 assert_eq!(&v[..], &[]);
3319 }
3320
3321 {
3322 let mut v = ThinVec::<i32>::new();
3323 let new = v.split_off(0);
3324 assert_eq!(v.len(), 0);
3325 assert_eq!(v.capacity(), 0);
3326 assert_eq!(&v[..], &[]);
3327
3328 assert_eq!(new.len(), 0);
3329 assert_eq!(new.capacity(), 0);
3330 assert_eq!(&new[..], &[]);
3331 }
3332
3333 {
3334 let mut v = ThinVec::<i32>::new();
3335 let mut other = ThinVec::<i32>::new();
3336 v.append(&mut other);
3337
3338 assert_eq!(v.len(), 0);
3339 assert_eq!(v.capacity(), 0);
3340 assert_eq!(&v[..], &[]);
3341
3342 assert_eq!(other.len(), 0);
3343 assert_eq!(other.capacity(), 0);
3344 assert_eq!(&other[..], &[]);
3345 }
3346
3347 {
3348 let mut v = ThinVec::<i32>::new();
3349 v.reserve(0);
3350
3351 assert_eq!(v.len(), 0);
3352 assert_eq!(v.capacity(), 0);
3353 assert_eq!(&v[..], &[]);
3354 }
3355
3356 {
3357 let mut v = ThinVec::<i32>::new();
3358 v.reserve_exact(0);
3359
3360 assert_eq!(v.len(), 0);
3361 assert_eq!(v.capacity(), 0);
3362 assert_eq!(&v[..], &[]);
3363 }
3364
3365 {
3366 let mut v = ThinVec::<i32>::new();
3367 v.reserve(0);
3368
3369 assert_eq!(v.len(), 0);
3370 assert_eq!(v.capacity(), 0);
3371 assert_eq!(&v[..], &[]);
3372 }
3373
3374 {
3375 let v = ThinVec::<i32>::with_capacity(0);
3376
3377 assert_eq!(v.len(), 0);
3378 assert_eq!(v.capacity(), 0);
3379 assert_eq!(&v[..], &[]);
3380 }
3381
3382 {
3383 let v = ThinVec::<i32>::default();
3384
3385 assert_eq!(v.len(), 0);
3386 assert_eq!(v.capacity(), 0);
3387 assert_eq!(&v[..], &[]);
3388 }
3389
3390 {
3391 let mut v = ThinVec::<i32>::new();
3392 v.retain(|_| unreachable!());
3393
3394 assert_eq!(v.len(), 0);
3395 assert_eq!(v.capacity(), 0);
3396 assert_eq!(&v[..], &[]);
3397 }
3398
3399 {
3400 let mut v = ThinVec::<i32>::new();
3401 v.retain_mut(|_| unreachable!());
3402
3403 assert_eq!(v.len(), 0);
3404 assert_eq!(v.capacity(), 0);
3405 assert_eq!(&v[..], &[]);
3406 }
3407
3408 {
3409 let mut v = ThinVec::<i32>::new();
3410 v.dedup_by_key(|x| *x);
3411
3412 assert_eq!(v.len(), 0);
3413 assert_eq!(v.capacity(), 0);
3414 assert_eq!(&v[..], &[]);
3415 }
3416
3417 {
3418 let mut v = ThinVec::<i32>::new();
3419 v.dedup_by(|_, _| unreachable!());
3420
3421 assert_eq!(v.len(), 0);
3422 assert_eq!(v.capacity(), 0);
3423 assert_eq!(&v[..], &[]);
3424 }
3425
3426 {
3427 let v = ThinVec::<i32>::new();
3428 let v = v.clone();
3429
3430 assert_eq!(v.len(), 0);
3431 assert_eq!(v.capacity(), 0);
3432 assert_eq!(&v[..], &[]);
3433 }
3434 }
3435
3436 #[test]
3437 fn test_clone() {
3438 let mut v = ThinVec::<i32>::new();
3439 assert!(v.is_singleton());
3440 v.push(0);
3441 v.pop();
3442 assert!(!v.is_singleton());
3443
3444 let v2 = v.clone();
3445 assert!(v2.is_singleton());
3446 }
3447}
3448
3449#[cfg(test)]
3450mod std_tests {
3451 #![allow(clippy::reversed_empty_ranges)]
3452
3453 use super::*;
3454 use crate::alloc::{
3455 format,
3456 string::{String, ToString},
3457 };
3458 use core::mem::size_of;
3459 use core::usize;
3460
3461 struct DropCounter<'a> {
3462 count: &'a mut u32,
3463 }
3464
3465 impl<'a> Drop for DropCounter<'a> {
3466 fn drop(&mut self) {
3467 *self.count += 1;
3468 }
3469 }
3470
3471 #[test]
3472 fn test_small_vec_struct() {
3473 assert!(size_of::<ThinVec<u8>>() == size_of::<usize>());
3474 }
3475
3476 #[test]
3477 fn test_double_drop() {
3478 struct TwoVec<T> {
3479 x: ThinVec<T>,
3480 y: ThinVec<T>,
3481 }
3482
3483 let (mut count_x, mut count_y) = (0, 0);
3484 {
3485 let mut tv = TwoVec {
3486 x: ThinVec::new(),
3487 y: ThinVec::new(),
3488 };
3489 tv.x.push(DropCounter {
3490 count: &mut count_x,
3491 });
3492 tv.y.push(DropCounter {
3493 count: &mut count_y,
3494 });
3495
3496 // If ThinVec had a drop flag, here is where it would be zeroed.
3497 // Instead, it should rely on its internal state to prevent
3498 // doing anything significant when dropped multiple times.
3499 drop(tv.x);
3500
3501 // Here tv goes out of scope, tv.y should be dropped, but not tv.x.
3502 }
3503
3504 assert_eq!(count_x, 1);
3505 assert_eq!(count_y, 1);
3506 }
3507
3508 #[test]
3509 fn test_reserve() {
3510 let mut v = ThinVec::new();
3511 assert_eq!(v.capacity(), 0);
3512
3513 v.reserve(2);
3514 assert!(v.capacity() >= 2);
3515
3516 for i in 0..16 {
3517 v.push(i);
3518 }
3519
3520 assert!(v.capacity() >= 16);
3521 v.reserve(16);
3522 assert!(v.capacity() >= 32);
3523
3524 v.push(16);
3525
3526 v.reserve(16);
3527 assert!(v.capacity() >= 33)
3528 }
3529
3530 #[test]
3531 fn test_extend() {
3532 let mut v = ThinVec::<usize>::new();
3533 let mut w = ThinVec::new();
3534 v.extend(w.clone());
3535 assert_eq!(v, &[]);
3536
3537 v.extend(0..3);
3538 for i in 0..3 {
3539 w.push(i)
3540 }
3541
3542 assert_eq!(v, w);
3543
3544 v.extend(3..10);
3545 for i in 3..10 {
3546 w.push(i)
3547 }
3548
3549 assert_eq!(v, w);
3550
3551 v.extend(w.clone()); // specializes to `append`
3552 assert!(v.iter().eq(w.iter().chain(w.iter())));
3553
3554 // Zero sized types
3555 #[derive(PartialEq, Debug)]
3556 struct Foo;
3557
3558 let mut a = ThinVec::new();
3559 let b = thin_vec![Foo, Foo];
3560
3561 a.extend(b);
3562 assert_eq!(a, &[Foo, Foo]);
3563
3564 // Double drop
3565 let mut count_x = 0;
3566 {
3567 let mut x = ThinVec::new();
3568 let y = thin_vec![DropCounter {
3569 count: &mut count_x
3570 }];
3571 x.extend(y);
3572 }
3573
3574 assert_eq!(count_x, 1);
3575 }
3576
3577 /* TODO: implement extend for Iter<&Copy>
3578 #[test]
3579 fn test_extend_ref() {
3580 let mut v = thin_vec![1, 2];
3581 v.extend(&[3, 4, 5]);
3582
3583 assert_eq!(v.len(), 5);
3584 assert_eq!(v, [1, 2, 3, 4, 5]);
3585
3586 let w = thin_vec![6, 7];
3587 v.extend(&w);
3588
3589 assert_eq!(v.len(), 7);
3590 assert_eq!(v, [1, 2, 3, 4, 5, 6, 7]);
3591 }
3592 */
3593
3594 #[test]
3595 fn test_slice_from_mut() {
3596 let mut values = thin_vec![1, 2, 3, 4, 5];
3597 {
3598 let slice = &mut values[2..];
3599 assert!(slice == [3, 4, 5]);
3600 for p in slice {
3601 *p += 2;
3602 }
3603 }
3604
3605 assert!(values == [1, 2, 5, 6, 7]);
3606 }
3607
3608 #[test]
3609 fn test_slice_to_mut() {
3610 let mut values = thin_vec![1, 2, 3, 4, 5];
3611 {
3612 let slice = &mut values[..2];
3613 assert!(slice == [1, 2]);
3614 for p in slice {
3615 *p += 1;
3616 }
3617 }
3618
3619 assert!(values == [2, 3, 3, 4, 5]);
3620 }
3621
3622 #[test]
3623 fn test_split_at_mut() {
3624 let mut values = thin_vec![1, 2, 3, 4, 5];
3625 {
3626 let (left, right) = values.split_at_mut(2);
3627 {
3628 let left: &[_] = left;
3629 assert!(left[..left.len()] == [1, 2]);
3630 }
3631 for p in left {
3632 *p += 1;
3633 }
3634
3635 {
3636 let right: &[_] = right;
3637 assert!(right[..right.len()] == [3, 4, 5]);
3638 }
3639 for p in right {
3640 *p += 2;
3641 }
3642 }
3643
3644 assert_eq!(values, [2, 3, 5, 6, 7]);
3645 }
3646
3647 #[test]
3648 fn test_clone() {
3649 let v: ThinVec<i32> = thin_vec![];
3650 let w = thin_vec![1, 2, 3];
3651
3652 assert_eq!(v, v.clone());
3653
3654 let z = w.clone();
3655 assert_eq!(w, z);
3656 // they should be disjoint in memory.
3657 assert!(w.as_ptr() != z.as_ptr())
3658 }
3659
3660 #[test]
3661 fn test_clone_from() {
3662 let mut v = thin_vec![];
3663 let three: ThinVec<Box<_>> = thin_vec![Box::new(1), Box::new(2), Box::new(3)];
3664 let two: ThinVec<Box<_>> = thin_vec![Box::new(4), Box::new(5)];
3665 // zero, long
3666 v.clone_from(&three);
3667 assert_eq!(v, three);
3668
3669 // equal
3670 v.clone_from(&three);
3671 assert_eq!(v, three);
3672
3673 // long, short
3674 v.clone_from(&two);
3675 assert_eq!(v, two);
3676
3677 // short, long
3678 v.clone_from(&three);
3679 assert_eq!(v, three)
3680 }
3681
3682 #[test]
3683 fn test_retain() {
3684 let mut vec = thin_vec![1, 2, 3, 4];
3685 vec.retain(|&x| x % 2 == 0);
3686 assert_eq!(vec, [2, 4]);
3687 }
3688
3689 #[test]
3690 fn test_retain_mut() {
3691 let mut vec = thin_vec![9, 9, 9, 9];
3692 let mut i = 0;
3693 vec.retain_mut(|x| {
3694 i += 1;
3695 *x = i;
3696 i != 4
3697 });
3698 assert_eq!(vec, [1, 2, 3]);
3699 }
3700
3701 #[test]
3702 fn test_dedup() {
3703 fn case(a: ThinVec<i32>, b: ThinVec<i32>) {
3704 let mut v = a;
3705 v.dedup();
3706 assert_eq!(v, b);
3707 }
3708 case(thin_vec![], thin_vec![]);
3709 case(thin_vec![1], thin_vec![1]);
3710 case(thin_vec![1, 1], thin_vec![1]);
3711 case(thin_vec![1, 2, 3], thin_vec![1, 2, 3]);
3712 case(thin_vec![1, 1, 2, 3], thin_vec![1, 2, 3]);
3713 case(thin_vec![1, 2, 2, 3], thin_vec![1, 2, 3]);
3714 case(thin_vec![1, 2, 3, 3], thin_vec![1, 2, 3]);
3715 case(thin_vec![1, 1, 2, 2, 2, 3, 3], thin_vec![1, 2, 3]);
3716 }
3717
3718 #[test]
3719 fn test_dedup_by_key() {
3720 fn case(a: ThinVec<i32>, b: ThinVec<i32>) {
3721 let mut v = a;
3722 v.dedup_by_key(|i| *i / 10);
3723 assert_eq!(v, b);
3724 }
3725 case(thin_vec![], thin_vec![]);
3726 case(thin_vec![10], thin_vec![10]);
3727 case(thin_vec![10, 11], thin_vec![10]);
3728 case(thin_vec![10, 20, 30], thin_vec![10, 20, 30]);
3729 case(thin_vec![10, 11, 20, 30], thin_vec![10, 20, 30]);
3730 case(thin_vec![10, 20, 21, 30], thin_vec![10, 20, 30]);
3731 case(thin_vec![10, 20, 30, 31], thin_vec![10, 20, 30]);
3732 case(thin_vec![10, 11, 20, 21, 22, 30, 31], thin_vec![10, 20, 30]);
3733 }
3734
3735 #[test]
3736 fn test_dedup_by() {
3737 let mut vec = thin_vec!["foo", "bar", "Bar", "baz", "bar"];
3738 vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
3739
3740 assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
3741
3742 let mut vec = thin_vec![("foo", 1), ("foo", 2), ("bar", 3), ("bar", 4), ("bar", 5)];
3743 vec.dedup_by(|a, b| {
3744 a.0 == b.0 && {
3745 b.1 += a.1;
3746 true
3747 }
3748 });
3749
3750 assert_eq!(vec, [("foo", 3), ("bar", 12)]);
3751 }
3752
3753 #[test]
3754 fn test_dedup_unique() {
3755 let mut v0: ThinVec<Box<_>> = thin_vec![Box::new(1), Box::new(1), Box::new(2), Box::new(3)];
3756 v0.dedup();
3757 let mut v1: ThinVec<Box<_>> = thin_vec![Box::new(1), Box::new(2), Box::new(2), Box::new(3)];
3758 v1.dedup();
3759 let mut v2: ThinVec<Box<_>> = thin_vec![Box::new(1), Box::new(2), Box::new(3), Box::new(3)];
3760 v2.dedup();
3761 // If the boxed pointers were leaked or otherwise misused, valgrind
3762 // and/or rt should raise errors.
3763 }
3764
3765 #[test]
3766 fn zero_sized_values() {
3767 let mut v = ThinVec::new();
3768 assert_eq!(v.len(), 0);
3769 v.push(());
3770 assert_eq!(v.len(), 1);
3771 v.push(());
3772 assert_eq!(v.len(), 2);
3773 assert_eq!(v.pop(), Some(()));
3774 assert_eq!(v.pop(), Some(()));
3775 assert_eq!(v.pop(), None);
3776
3777 assert_eq!(v.iter().count(), 0);
3778 v.push(());
3779 assert_eq!(v.iter().count(), 1);
3780 v.push(());
3781 assert_eq!(v.iter().count(), 2);
3782
3783 for &() in &v {}
3784
3785 assert_eq!(v.iter_mut().count(), 2);
3786 v.push(());
3787 assert_eq!(v.iter_mut().count(), 3);
3788 v.push(());
3789 assert_eq!(v.iter_mut().count(), 4);
3790
3791 for &mut () in &mut v {}
3792 unsafe {
3793 v.set_len(0);
3794 }
3795 assert_eq!(v.iter_mut().count(), 0);
3796 }
3797
3798 #[test]
3799 fn test_partition() {
3800 assert_eq!(
3801 thin_vec![].into_iter().partition(|x: &i32| *x < 3),
3802 (thin_vec![], thin_vec![])
3803 );
3804 assert_eq!(
3805 thin_vec![1, 2, 3].into_iter().partition(|x| *x < 4),
3806 (thin_vec![1, 2, 3], thin_vec![])
3807 );
3808 assert_eq!(
3809 thin_vec![1, 2, 3].into_iter().partition(|x| *x < 2),
3810 (thin_vec![1], thin_vec![2, 3])
3811 );
3812 assert_eq!(
3813 thin_vec![1, 2, 3].into_iter().partition(|x| *x < 0),
3814 (thin_vec![], thin_vec![1, 2, 3])
3815 );
3816 }
3817
3818 #[test]
3819 fn test_zip_unzip() {
3820 let z1 = thin_vec![(1, 4), (2, 5), (3, 6)];
3821
3822 let (left, right): (ThinVec<_>, ThinVec<_>) = z1.iter().cloned().unzip();
3823
3824 assert_eq!((1, 4), (left[0], right[0]));
3825 assert_eq!((2, 5), (left[1], right[1]));
3826 assert_eq!((3, 6), (left[2], right[2]));
3827 }
3828
3829 #[test]
3830 fn test_vec_truncate_drop() {
3831 static mut DROPS: u32 = 0;
3832 struct Elem(i32);
3833 impl Drop for Elem {
3834 fn drop(&mut self) {
3835 unsafe {
3836 DROPS += 1;
3837 }
3838 }
3839 }
3840
3841 let mut v = thin_vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)];
3842 assert_eq!(unsafe { DROPS }, 0);
3843 v.truncate(3);
3844 assert_eq!(unsafe { DROPS }, 2);
3845 v.truncate(0);
3846 assert_eq!(unsafe { DROPS }, 5);
3847 }
3848
3849 #[test]
3850 #[should_panic]
3851 fn test_vec_truncate_fail() {
3852 struct BadElem(i32);
3853 impl Drop for BadElem {
3854 fn drop(&mut self) {
3855 let BadElem(ref mut x) = *self;
3856 if *x == 0xbadbeef {
3857 panic!("BadElem panic: 0xbadbeef")
3858 }
3859 }
3860 }
3861
3862 let mut v = thin_vec![BadElem(1), BadElem(2), BadElem(0xbadbeef), BadElem(4)];
3863 v.truncate(0);
3864 }
3865
3866 #[test]
3867 fn test_index() {
3868 let vec = thin_vec![1, 2, 3];
3869 assert!(vec[1] == 2);
3870 }
3871
3872 #[test]
3873 #[should_panic]
3874 fn test_index_out_of_bounds() {
3875 let vec = thin_vec![1, 2, 3];
3876 let _ = vec[3];
3877 }
3878
3879 #[test]
3880 #[should_panic]
3881 fn test_slice_out_of_bounds_1() {
3882 let x = thin_vec![1, 2, 3, 4, 5];
3883 let _ = &x[!0..];
3884 }
3885
3886 #[test]
3887 #[should_panic]
3888 fn test_slice_out_of_bounds_2() {
3889 let x = thin_vec![1, 2, 3, 4, 5];
3890 let _ = &x[..6];
3891 }
3892
3893 #[test]
3894 #[should_panic]
3895 fn test_slice_out_of_bounds_3() {
3896 let x = thin_vec![1, 2, 3, 4, 5];
3897 let _ = &x[!0..4];
3898 }
3899
3900 #[test]
3901 #[should_panic]
3902 fn test_slice_out_of_bounds_4() {
3903 let x = thin_vec![1, 2, 3, 4, 5];
3904 let _ = &x[1..6];
3905 }
3906
3907 #[test]
3908 #[should_panic]
3909 fn test_slice_out_of_bounds_5() {
3910 let x = thin_vec![1, 2, 3, 4, 5];
3911 let _ = &x[3..2];
3912 }
3913
3914 #[test]
3915 #[should_panic]
3916 fn test_swap_remove_empty() {
3917 let mut vec = ThinVec::<i32>::new();
3918 vec.swap_remove(0);
3919 }
3920
3921 #[test]
3922 fn test_move_items() {
3923 let vec = thin_vec![1, 2, 3];
3924 let mut vec2 = thin_vec![];
3925 for i in vec {
3926 vec2.push(i);
3927 }
3928 assert_eq!(vec2, [1, 2, 3]);
3929 }
3930
3931 #[test]
3932 fn test_move_items_reverse() {
3933 let vec = thin_vec![1, 2, 3];
3934 let mut vec2 = thin_vec![];
3935 for i in vec.into_iter().rev() {
3936 vec2.push(i);
3937 }
3938 assert_eq!(vec2, [3, 2, 1]);
3939 }
3940
3941 #[test]
3942 fn test_move_items_zero_sized() {
3943 let vec = thin_vec![(), (), ()];
3944 let mut vec2 = thin_vec![];
3945 for i in vec {
3946 vec2.push(i);
3947 }
3948 assert_eq!(vec2, [(), (), ()]);
3949 }
3950
3951 #[test]
3952 fn test_drain_items() {
3953 let mut vec = thin_vec![1, 2, 3];
3954 let mut vec2 = thin_vec![];
3955 for i in vec.drain(..) {
3956 vec2.push(i);
3957 }
3958 assert_eq!(vec, []);
3959 assert_eq!(vec2, [1, 2, 3]);
3960 }
3961
3962 #[test]
3963 fn test_drain_items_reverse() {
3964 let mut vec = thin_vec![1, 2, 3];
3965 let mut vec2 = thin_vec![];
3966 for i in vec.drain(..).rev() {
3967 vec2.push(i);
3968 }
3969 assert_eq!(vec, []);
3970 assert_eq!(vec2, [3, 2, 1]);
3971 }
3972
3973 #[test]
3974 fn test_drain_items_zero_sized() {
3975 let mut vec = thin_vec![(), (), ()];
3976 let mut vec2 = thin_vec![];
3977 for i in vec.drain(..) {
3978 vec2.push(i);
3979 }
3980 assert_eq!(vec, []);
3981 assert_eq!(vec2, [(), (), ()]);
3982 }
3983
3984 #[test]
3985 #[should_panic]
3986 fn test_drain_out_of_bounds() {
3987 let mut v = thin_vec![1, 2, 3, 4, 5];
3988 v.drain(5..6);
3989 }
3990
3991 #[test]
3992 fn test_drain_range() {
3993 let mut v = thin_vec![1, 2, 3, 4, 5];
3994 for _ in v.drain(4..) {}
3995 assert_eq!(v, &[1, 2, 3, 4]);
3996
3997 let mut v: ThinVec<_> = (1..6).map(|x| x.to_string()).collect();
3998 for _ in v.drain(1..4) {}
3999 assert_eq!(v, &[1.to_string(), 5.to_string()]);
4000
4001 let mut v: ThinVec<_> = (1..6).map(|x| x.to_string()).collect();
4002 for _ in v.drain(1..4).rev() {}
4003 assert_eq!(v, &[1.to_string(), 5.to_string()]);
4004
4005 let mut v: ThinVec<_> = thin_vec![(); 5];
4006 for _ in v.drain(1..4).rev() {}
4007 assert_eq!(v, &[(), ()]);
4008 }
4009
4010 #[test]
4011 fn test_drain_inclusive_range() {
4012 let mut v = thin_vec!['a', 'b', 'c', 'd', 'e'];
4013 for _ in v.drain(1..=3) {}
4014 assert_eq!(v, &['a', 'e']);
4015
4016 let mut v: ThinVec<_> = (0..=5).map(|x| x.to_string()).collect();
4017 for _ in v.drain(1..=5) {}
4018 assert_eq!(v, &["0".to_string()]);
4019
4020 let mut v: ThinVec<String> = (0..=5).map(|x| x.to_string()).collect();
4021 for _ in v.drain(0..=5) {}
4022 assert_eq!(v, ThinVec::<String>::new());
4023
4024 let mut v: ThinVec<_> = (0..=5).map(|x| x.to_string()).collect();
4025 for _ in v.drain(0..=3) {}
4026 assert_eq!(v, &["4".to_string(), "5".to_string()]);
4027
4028 let mut v: ThinVec<_> = (0..=1).map(|x| x.to_string()).collect();
4029 for _ in v.drain(..=0) {}
4030 assert_eq!(v, &["1".to_string()]);
4031 }
4032
4033 #[test]
4034 #[cfg(not(feature = "gecko-ffi"))]
4035 fn test_drain_max_vec_size() {
4036 let mut v = ThinVec::<()>::with_capacity(usize::max_value());
4037 unsafe {
4038 v.set_len(usize::max_value());
4039 }
4040 for _ in v.drain(usize::max_value() - 1..) {}
4041 assert_eq!(v.len(), usize::max_value() - 1);
4042
4043 let mut v = ThinVec::<()>::with_capacity(usize::max_value());
4044 unsafe {
4045 v.set_len(usize::max_value());
4046 }
4047 for _ in v.drain(usize::max_value() - 1..=usize::max_value() - 1) {}
4048 assert_eq!(v.len(), usize::max_value() - 1);
4049 }
4050
4051 #[test]
4052 #[should_panic]
4053 fn test_drain_inclusive_out_of_bounds() {
4054 let mut v = thin_vec![1, 2, 3, 4, 5];
4055 v.drain(5..=5);
4056 }
4057
4058 #[test]
4059 fn test_splice() {
4060 let mut v = thin_vec![1, 2, 3, 4, 5];
4061 let a = [10, 11, 12];
4062 v.splice(2..4, a.iter().cloned());
4063 assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
4064 v.splice(1..3, Some(20));
4065 assert_eq!(v, &[1, 20, 11, 12, 5]);
4066 }
4067
4068 #[test]
4069 fn test_splice_inclusive_range() {
4070 let mut v = thin_vec![1, 2, 3, 4, 5];
4071 let a = [10, 11, 12];
4072 let t1: ThinVec<_> = v.splice(2..=3, a.iter().cloned()).collect();
4073 assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
4074 assert_eq!(t1, &[3, 4]);
4075 let t2: ThinVec<_> = v.splice(1..=2, Some(20)).collect();
4076 assert_eq!(v, &[1, 20, 11, 12, 5]);
4077 assert_eq!(t2, &[2, 10]);
4078 }
4079
4080 #[test]
4081 #[should_panic]
4082 fn test_splice_out_of_bounds() {
4083 let mut v = thin_vec![1, 2, 3, 4, 5];
4084 let a = [10, 11, 12];
4085 v.splice(5..6, a.iter().cloned());
4086 }
4087
4088 #[test]
4089 #[should_panic]
4090 fn test_splice_inclusive_out_of_bounds() {
4091 let mut v = thin_vec![1, 2, 3, 4, 5];
4092 let a = [10, 11, 12];
4093 v.splice(5..=5, a.iter().cloned());
4094 }
4095
4096 #[test]
4097 fn test_splice_items_zero_sized() {
4098 let mut vec = thin_vec![(), (), ()];
4099 let vec2 = thin_vec![];
4100 let t: ThinVec<_> = vec.splice(1..2, vec2.iter().cloned()).collect();
4101 assert_eq!(vec, &[(), ()]);
4102 assert_eq!(t, &[()]);
4103 }
4104
4105 #[test]
4106 fn test_splice_unbounded() {
4107 let mut vec = thin_vec![1, 2, 3, 4, 5];
4108 let t: ThinVec<_> = vec.splice(.., None).collect();
4109 assert_eq!(vec, &[]);
4110 assert_eq!(t, &[1, 2, 3, 4, 5]);
4111 }
4112
4113 #[test]
4114 fn test_splice_forget() {
4115 let mut v = thin_vec![1, 2, 3, 4, 5];
4116 let a = [10, 11, 12];
4117 ::core::mem::forget(v.splice(2..4, a.iter().cloned()));
4118 assert_eq!(v, &[1, 2]);
4119 }
4120
4121 #[test]
4122 fn test_splice_from_empty() {
4123 let mut v = thin_vec![];
4124 let a = [10, 11, 12];
4125 v.splice(.., a.iter().cloned());
4126 assert_eq!(v, &[10, 11, 12]);
4127 }
4128
4129 /* probs won't ever impl this
4130 #[test]
4131 fn test_into_boxed_slice() {
4132 let xs = thin_vec![1, 2, 3];
4133 let ys = xs.into_boxed_slice();
4134 assert_eq!(&*ys, [1, 2, 3]);
4135 }
4136 */
4137
4138 #[test]
4139 fn test_append() {
4140 let mut vec = thin_vec![1, 2, 3];
4141 let mut vec2 = thin_vec![4, 5, 6];
4142 vec.append(&mut vec2);
4143 assert_eq!(vec, [1, 2, 3, 4, 5, 6]);
4144 assert_eq!(vec2, []);
4145 }
4146
4147 #[test]
4148 fn test_split_off() {
4149 let mut vec = thin_vec![1, 2, 3, 4, 5, 6];
4150 let vec2 = vec.split_off(4);
4151 assert_eq!(vec, [1, 2, 3, 4]);
4152 assert_eq!(vec2, [5, 6]);
4153 }
4154
4155 #[test]
4156 fn test_into_iter_as_slice() {
4157 let vec = thin_vec!['a', 'b', 'c'];
4158 let mut into_iter = vec.into_iter();
4159 assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
4160 let _ = into_iter.next().unwrap();
4161 assert_eq!(into_iter.as_slice(), &['b', 'c']);
4162 let _ = into_iter.next().unwrap();
4163 let _ = into_iter.next().unwrap();
4164 assert_eq!(into_iter.as_slice(), &[]);
4165 }
4166
4167 #[test]
4168 fn test_into_iter_as_mut_slice() {
4169 let vec = thin_vec!['a', 'b', 'c'];
4170 let mut into_iter = vec.into_iter();
4171 assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
4172 into_iter.as_mut_slice()[0] = 'x';
4173 into_iter.as_mut_slice()[1] = 'y';
4174 assert_eq!(into_iter.next().unwrap(), 'x');
4175 assert_eq!(into_iter.as_slice(), &['y', 'c']);
4176 }
4177
4178 #[test]
4179 fn test_into_iter_debug() {
4180 let vec = thin_vec!['a', 'b', 'c'];
4181 let into_iter = vec.into_iter();
4182 let debug = format!("{:?}", into_iter);
4183 assert_eq!(debug, "IntoIter(['a', 'b', 'c'])");
4184 }
4185
4186 #[test]
4187 fn test_into_iter_count() {
4188 assert_eq!(thin_vec![1, 2, 3].into_iter().count(), 3);
4189 }
4190
4191 #[test]
4192 fn test_into_iter_clone() {
4193 fn iter_equal<I: Iterator<Item = i32>>(it: I, slice: &[i32]) {
4194 let v: ThinVec<i32> = it.collect();
4195 assert_eq!(&v[..], slice);
4196 }
4197 let mut it = thin_vec![1, 2, 3].into_iter();
4198 iter_equal(it.clone(), &[1, 2, 3]);
4199 assert_eq!(it.next(), Some(1));
4200 let mut it = it.rev();
4201 iter_equal(it.clone(), &[3, 2]);
4202 assert_eq!(it.next(), Some(3));
4203 iter_equal(it.clone(), &[2]);
4204 assert_eq!(it.next(), Some(2));
4205 iter_equal(it.clone(), &[]);
4206 assert_eq!(it.next(), None);
4207 }
4208
4209 #[allow(dead_code)]
4210 fn assert_covariance() {
4211 fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
4212 d
4213 }
4214 fn into_iter<'new>(i: IntoIter<&'static str>) -> IntoIter<&'new str> {
4215 i
4216 }
4217 }
4218
4219 /* TODO: specialize vec.into_iter().collect::<ThinVec<_>>();
4220 #[test]
4221 fn from_into_inner() {
4222 let vec = thin_vec![1, 2, 3];
4223 let ptr = vec.as_ptr();
4224 let vec = vec.into_iter().collect::<ThinVec<_>>();
4225 assert_eq!(vec, [1, 2, 3]);
4226 assert_eq!(vec.as_ptr(), ptr);
4227
4228 let ptr = &vec[1] as *const _;
4229 let mut it = vec.into_iter();
4230 it.next().unwrap();
4231 let vec = it.collect::<ThinVec<_>>();
4232 assert_eq!(vec, [2, 3]);
4233 assert!(ptr != vec.as_ptr());
4234 }
4235 */
4236
4237 #[test]
4238 #[cfg_attr(feature = "gecko-ffi", ignore)]
4239 fn overaligned_allocations() {
4240 #[repr(align(256))]
4241 struct Foo(usize);
4242 let mut v = thin_vec![Foo(273)];
4243 for i in 0..0x1000 {
4244 v.reserve_exact(i);
4245 assert!(v[0].0 == 273);
4246 assert!(v.as_ptr() as usize & 0xff == 0);
4247 v.shrink_to_fit();
4248 assert!(v[0].0 == 273);
4249 assert!(v.as_ptr() as usize & 0xff == 0);
4250 }
4251 }
4252
4253 /* TODO: implement drain_filter?
4254 #[test]
4255 fn drain_filter_empty() {
4256 let mut vec: ThinVec<i32> = thin_vec![];
4257
4258 {
4259 let mut iter = vec.drain_filter(|_| true);
4260 assert_eq!(iter.size_hint(), (0, Some(0)));
4261 assert_eq!(iter.next(), None);
4262 assert_eq!(iter.size_hint(), (0, Some(0)));
4263 assert_eq!(iter.next(), None);
4264 assert_eq!(iter.size_hint(), (0, Some(0)));
4265 }
4266 assert_eq!(vec.len(), 0);
4267 assert_eq!(vec, thin_vec![]);
4268 }
4269
4270 #[test]
4271 fn drain_filter_zst() {
4272 let mut vec = thin_vec![(), (), (), (), ()];
4273 let initial_len = vec.len();
4274 let mut count = 0;
4275 {
4276 let mut iter = vec.drain_filter(|_| true);
4277 assert_eq!(iter.size_hint(), (0, Some(initial_len)));
4278 while let Some(_) = iter.next() {
4279 count += 1;
4280 assert_eq!(iter.size_hint(), (0, Some(initial_len - count)));
4281 }
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
4287 assert_eq!(count, initial_len);
4288 assert_eq!(vec.len(), 0);
4289 assert_eq!(vec, thin_vec![]);
4290 }
4291
4292 #[test]
4293 fn drain_filter_false() {
4294 let mut vec = thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
4295
4296 let initial_len = vec.len();
4297 let mut count = 0;
4298 {
4299 let mut iter = vec.drain_filter(|_| false);
4300 assert_eq!(iter.size_hint(), (0, Some(initial_len)));
4301 for _ in iter.by_ref() {
4302 count += 1;
4303 }
4304 assert_eq!(iter.size_hint(), (0, Some(0)));
4305 assert_eq!(iter.next(), None);
4306 assert_eq!(iter.size_hint(), (0, Some(0)));
4307 }
4308
4309 assert_eq!(count, 0);
4310 assert_eq!(vec.len(), initial_len);
4311 assert_eq!(vec, thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
4312 }
4313
4314 #[test]
4315 fn drain_filter_true() {
4316 let mut vec = thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
4317
4318 let initial_len = vec.len();
4319 let mut count = 0;
4320 {
4321 let mut iter = vec.drain_filter(|_| true);
4322 assert_eq!(iter.size_hint(), (0, Some(initial_len)));
4323 while let Some(_) = iter.next() {
4324 count += 1;
4325 assert_eq!(iter.size_hint(), (0, Some(initial_len - count)));
4326 }
4327 assert_eq!(iter.size_hint(), (0, Some(0)));
4328 assert_eq!(iter.next(), None);
4329 assert_eq!(iter.size_hint(), (0, Some(0)));
4330 }
4331
4332 assert_eq!(count, initial_len);
4333 assert_eq!(vec.len(), 0);
4334 assert_eq!(vec, thin_vec![]);
4335 }
4336
4337 #[test]
4338 fn drain_filter_complex() {
4339
4340 { // [+xxx++++++xxxxx++++x+x++]
4341 let mut vec = thin_vec![1,
4342 2, 4, 6,
4343 7, 9, 11, 13, 15, 17,
4344 18, 20, 22, 24, 26,
4345 27, 29, 31, 33,
4346 34,
4347 35,
4348 36,
4349 37, 39];
4350
4351 let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<ThinVec<_>>();
4352 assert_eq!(removed.len(), 10);
4353 assert_eq!(removed, thin_vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
4354
4355 assert_eq!(vec.len(), 14);
4356 assert_eq!(vec, thin_vec![1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]);
4357 }
4358
4359 { // [xxx++++++xxxxx++++x+x++]
4360 let mut vec = thin_vec![2, 4, 6,
4361 7, 9, 11, 13, 15, 17,
4362 18, 20, 22, 24, 26,
4363 27, 29, 31, 33,
4364 34,
4365 35,
4366 36,
4367 37, 39];
4368
4369 let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<ThinVec<_>>();
4370 assert_eq!(removed.len(), 10);
4371 assert_eq!(removed, thin_vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
4372
4373 assert_eq!(vec.len(), 13);
4374 assert_eq!(vec, thin_vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]);
4375 }
4376
4377 { // [xxx++++++xxxxx++++x+x]
4378 let mut vec = thin_vec![2, 4, 6,
4379 7, 9, 11, 13, 15, 17,
4380 18, 20, 22, 24, 26,
4381 27, 29, 31, 33,
4382 34,
4383 35,
4384 36];
4385
4386 let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<ThinVec<_>>();
4387 assert_eq!(removed.len(), 10);
4388 assert_eq!(removed, thin_vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
4389
4390 assert_eq!(vec.len(), 11);
4391 assert_eq!(vec, thin_vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35]);
4392 }
4393
4394 { // [xxxxxxxxxx+++++++++++]
4395 let mut vec = thin_vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
4396 1, 3, 5, 7, 9, 11, 13, 15, 17, 19];
4397
4398 let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<ThinVec<_>>();
4399 assert_eq!(removed.len(), 10);
4400 assert_eq!(removed, thin_vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);
4401
4402 assert_eq!(vec.len(), 10);
4403 assert_eq!(vec, thin_vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
4404 }
4405
4406 { // [+++++++++++xxxxxxxxxx]
4407 let mut vec = thin_vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19,
4408 2, 4, 6, 8, 10, 12, 14, 16, 18, 20];
4409
4410 let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<ThinVec<_>>();
4411 assert_eq!(removed.len(), 10);
4412 assert_eq!(removed, thin_vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);
4413
4414 assert_eq!(vec.len(), 10);
4415 assert_eq!(vec, thin_vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
4416 }
4417 }
4418 */
4419 #[test]
4420 fn test_reserve_exact() {
4421 // This is all the same as test_reserve
4422
4423 let mut v = ThinVec::new();
4424 assert_eq!(v.capacity(), 0);
4425
4426 v.reserve_exact(2);
4427 assert!(v.capacity() >= 2);
4428
4429 for i in 0..16 {
4430 v.push(i);
4431 }
4432
4433 assert!(v.capacity() >= 16);
4434 v.reserve_exact(16);
4435 assert!(v.capacity() >= 32);
4436
4437 v.push(16);
4438
4439 v.reserve_exact(16);
4440 assert!(v.capacity() >= 33)
4441 }
4442
4443 /* TODO: implement try_reserve
4444 #[test]
4445 fn test_try_reserve() {
4446
4447 // These are the interesting cases:
4448 // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM)
4449 // * > isize::MAX should always fail
4450 // * On 16/32-bit should CapacityOverflow
4451 // * On 64-bit should OOM
4452 // * overflow may trigger when adding `len` to `cap` (in number of elements)
4453 // * overflow may trigger when multiplying `new_cap` by size_of::<T> (to get bytes)
4454
4455 const MAX_CAP: usize = isize::MAX as usize;
4456 const MAX_USIZE: usize = usize::MAX;
4457
4458 // On 16/32-bit, we check that allocations don't exceed isize::MAX,
4459 // on 64-bit, we assume the OS will give an OOM for such a ridiculous size.
4460 // Any platform that succeeds for these requests is technically broken with
4461 // ptr::offset because LLVM is the worst.
4462 let guards_against_isize = size_of::<usize>() < 8;
4463
4464 {
4465 // Note: basic stuff is checked by test_reserve
4466 let mut empty_bytes: ThinVec<u8> = ThinVec::new();
4467
4468 // Check isize::MAX doesn't count as an overflow
4469 if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) {
4470 panic!("isize::MAX shouldn't trigger an overflow!");
4471 }
4472 // Play it again, frank! (just to be sure)
4473 if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) {
4474 panic!("isize::MAX shouldn't trigger an overflow!");
4475 }
4476
4477 if guards_against_isize {
4478 // Check isize::MAX + 1 does count as overflow
4479 if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP + 1) {
4480 } else { panic!("isize::MAX + 1 should trigger an overflow!") }
4481
4482 // Check usize::MAX does count as overflow
4483 if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) {
4484 } else { panic!("usize::MAX should trigger an overflow!") }
4485 } else {
4486 // Check isize::MAX + 1 is an OOM
4487 if let Err(AllocErr) = empty_bytes.try_reserve(MAX_CAP + 1) {
4488 } else { panic!("isize::MAX + 1 should trigger an OOM!") }
4489
4490 // Check usize::MAX is an OOM
4491 if let Err(AllocErr) = empty_bytes.try_reserve(MAX_USIZE) {
4492 } else { panic!("usize::MAX should trigger an OOM!") }
4493 }
4494 }
4495
4496
4497 {
4498 // Same basic idea, but with non-zero len
4499 let mut ten_bytes: ThinVec<u8> = thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
4500
4501 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) {
4502 panic!("isize::MAX shouldn't trigger an overflow!");
4503 }
4504 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) {
4505 panic!("isize::MAX shouldn't trigger an overflow!");
4506 }
4507 if guards_against_isize {
4508 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) {
4509 } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
4510 } else {
4511 if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) {
4512 } else { panic!("isize::MAX + 1 should trigger an OOM!") }
4513 }
4514 // Should always overflow in the add-to-len
4515 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) {
4516 } else { panic!("usize::MAX should trigger an overflow!") }
4517 }
4518
4519
4520 {
4521 // Same basic idea, but with interesting type size
4522 let mut ten_u32s: ThinVec<u32> = thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
4523
4524 if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 10) {
4525 panic!("isize::MAX shouldn't trigger an overflow!");
4526 }
4527 if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 10) {
4528 panic!("isize::MAX shouldn't trigger an overflow!");
4529 }
4530 if guards_against_isize {
4531 if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
4532 } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
4533 } else {
4534 if let Err(AllocErr) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
4535 } else { panic!("isize::MAX + 1 should trigger an OOM!") }
4536 }
4537 // Should fail in the mul-by-size
4538 if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_USIZE - 20) {
4539 } else {
4540 panic!("usize::MAX should trigger an overflow!");
4541 }
4542 }
4543
4544 }
4545
4546 #[test]
4547 fn test_try_reserve_exact() {
4548
4549 // This is exactly the same as test_try_reserve with the method changed.
4550 // See that test for comments.
4551
4552 const MAX_CAP: usize = isize::MAX as usize;
4553 const MAX_USIZE: usize = usize::MAX;
4554
4555 let guards_against_isize = size_of::<usize>() < 8;
4556
4557 {
4558 let mut empty_bytes: ThinVec<u8> = ThinVec::new();
4559
4560 if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) {
4561 panic!("isize::MAX shouldn't trigger an overflow!");
4562 }
4563 if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) {
4564 panic!("isize::MAX shouldn't trigger an overflow!");
4565 }
4566
4567 if guards_against_isize {
4568 if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP + 1) {
4569 } else { panic!("isize::MAX + 1 should trigger an overflow!") }
4570
4571 if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_USIZE) {
4572 } else { panic!("usize::MAX should trigger an overflow!") }
4573 } else {
4574 if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_CAP + 1) {
4575 } else { panic!("isize::MAX + 1 should trigger an OOM!") }
4576
4577 if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_USIZE) {
4578 } else { panic!("usize::MAX should trigger an OOM!") }
4579 }
4580 }
4581
4582
4583 {
4584 let mut ten_bytes: ThinVec<u8> = thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
4585
4586 if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) {
4587 panic!("isize::MAX shouldn't trigger an overflow!");
4588 }
4589 if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) {
4590 panic!("isize::MAX shouldn't trigger an overflow!");
4591 }
4592 if guards_against_isize {
4593 if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
4594 } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
4595 } else {
4596 if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
4597 } else { panic!("isize::MAX + 1 should trigger an OOM!") }
4598 }
4599 if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) {
4600 } else { panic!("usize::MAX should trigger an overflow!") }
4601 }
4602
4603
4604 {
4605 let mut ten_u32s: ThinVec<u32> = thin_vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
4606
4607 if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 10) {
4608 panic!("isize::MAX shouldn't trigger an overflow!");
4609 }
4610 if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 10) {
4611 panic!("isize::MAX shouldn't trigger an overflow!");
4612 }
4613 if guards_against_isize {
4614 if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
4615 } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
4616 } else {
4617 if let Err(AllocErr) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
4618 } else { panic!("isize::MAX + 1 should trigger an OOM!") }
4619 }
4620 if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) {
4621 } else { panic!("usize::MAX should trigger an overflow!") }
4622 }
4623 }
4624 */
4625
4626 #[cfg(feature = "gecko-ffi")]
4627 #[test]
4628 fn auto_t_array_basic() {
4629 crate::auto_thin_vec!(let t: [u8; 10]);
4630 assert_eq!(t.capacity(), 10);
4631 assert!(t.is_auto_array());
4632 assert!(t.uses_stack_allocated_buffer());
4633 assert!(!t.has_allocation());
4634 {
4635 let inner = unsafe { &mut *t.as_mut().as_mut_ptr() };
4636 for i in 0..30 {
4637 inner.push(i as u8);
4638 }
4639 }
4640
4641 assert!(t.is_auto_array());
4642 assert!(!t.uses_stack_allocated_buffer());
4643 assert_eq!(t.len(), 30);
4644 assert!(t.has_allocation());
4645 assert_eq!(t[5], 5);
4646 assert_eq!(t[29], 29);
4647 assert!(t.capacity() >= 30);
4648
4649 {
4650 let inner = unsafe { &mut *t.as_mut().as_mut_ptr() };
4651 inner.truncate(5);
4652 }
4653
4654 assert_eq!(t.len(), 5);
4655 assert!(t.capacity() >= 30);
4656 assert!(t.has_allocation());
4657 t.as_mut().shrink_to_fit();
4658 assert!(!t.has_allocation());
4659 assert!(t.is_auto_array());
4660 assert!(t.uses_stack_allocated_buffer());
4661 assert_eq!(t.capacity(), 10);
4662 }
4663
4664 #[test]
4665 #[cfg_attr(feature = "gecko-ffi", ignore)]
4666 fn test_header_data() {
4667 macro_rules! assert_aligned_head_ptr {
4668 ($typename:ty) => {{
4669 let v: ThinVec<$typename> = ThinVec::with_capacity(1 /* ensure allocation */);
4670 let head_ptr: *mut $typename = v.data_raw();
4671 assert_eq!(
4672 head_ptr as usize % core::mem::align_of::<$typename>(),
4673 0,
4674 "expected Header::data<{}> to be aligned",
4675 stringify!($typename)
4676 );
4677 }};
4678 }
4679
4680 const HEADER_SIZE: usize = core::mem::size_of::<Header>();
4681 assert_eq!(2 * core::mem::size_of::<usize>(), HEADER_SIZE);
4682
4683 #[repr(C, align(128))]
4684 struct Funky<T>(T);
4685 assert_eq!(padding::<Funky<()>>(), 128 - HEADER_SIZE);
4686 assert_aligned_head_ptr!(Funky<()>);
4687
4688 assert_eq!(padding::<Funky<u8>>(), 128 - HEADER_SIZE);
4689 assert_aligned_head_ptr!(Funky<u8>);
4690
4691 assert_eq!(padding::<Funky<[(); 1024]>>(), 128 - HEADER_SIZE);
4692 assert_aligned_head_ptr!(Funky<[(); 1024]>);
4693
4694 assert_eq!(padding::<Funky<[*mut usize; 1024]>>(), 128 - HEADER_SIZE);
4695 assert_aligned_head_ptr!(Funky<[*mut usize; 1024]>);
4696 }
4697
4698 #[cfg(feature = "serde")]
4699 use serde_test::{assert_tokens, Token};
4700
4701 #[test]
4702 #[cfg(feature = "serde")]
4703 fn test_ser_de_empty() {
4704 let vec = ThinVec::<u32>::new();
4705
4706 assert_tokens(&vec, &[Token::Seq { len: Some(0) }, Token::SeqEnd]);
4707 }
4708
4709 #[test]
4710 #[cfg(feature = "serde")]
4711 fn test_ser_de() {
4712 let mut vec = ThinVec::<u32>::new();
4713 vec.push(20);
4714 vec.push(55);
4715 vec.push(123);
4716
4717 assert_tokens(
4718 &vec,
4719 &[
4720 Token::Seq { len: Some(3) },
4721 Token::U32(20),
4722 Token::U32(55),
4723 Token::U32(123),
4724 Token::SeqEnd,
4725 ],
4726 );
4727 }
4728
4729 #[test]
4730 fn test_set_len() {
4731 let mut vec: ThinVec<u32> = thin_vec![];
4732 unsafe {
4733 vec.set_len(0); // at one point this caused a crash
4734 }
4735 }
4736
4737 #[test]
4738 #[should_panic(expected = "invalid set_len(1) on empty ThinVec")]
4739 fn test_set_len_invalid() {
4740 let mut vec: ThinVec<u32> = thin_vec![];
4741 unsafe {
4742 vec.set_len(1);
4743 }
4744 }
4745
4746 #[test]
4747 #[should_panic(expected = "capacity overflow")]
4748 fn test_capacity_overflow_header_too_big() {
4749 let vec: ThinVec<u8> = ThinVec::with_capacity(isize::MAX as usize - 2);
4750 assert!(vec.capacity() > 0);
4751 }
4752 #[test]
4753 #[should_panic(expected = "capacity overflow")]
4754 fn test_capacity_overflow_cap_too_big() {
4755 let vec: ThinVec<u8> = ThinVec::with_capacity(isize::MAX as usize + 1);
4756 assert!(vec.capacity() > 0);
4757 }
4758 #[test]
4759 #[should_panic(expected = "capacity overflow")]
4760 fn test_capacity_overflow_size_mul1() {
4761 let vec: ThinVec<u16> = ThinVec::with_capacity(isize::MAX as usize + 1);
4762 assert!(vec.capacity() > 0);
4763 }
4764 #[test]
4765 #[should_panic(expected = "capacity overflow")]
4766 fn test_capacity_overflow_size_mul2() {
4767 let vec: ThinVec<u16> = ThinVec::with_capacity(isize::MAX as usize / 2 + 1);
4768 assert!(vec.capacity() > 0);
4769 }
4770 #[test]
4771 #[should_panic(expected = "capacity overflow")]
4772 fn test_capacity_overflow_cap_really_isnt_isize() {
4773 let vec: ThinVec<u8> = ThinVec::with_capacity(isize::MAX as usize);
4774 assert!(vec.capacity() > 0);
4775 }
4776}