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