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