Skip to main content

planck_noalloc/
smallvec.rs

1//! A vector that stores elements inline up to a fixed capacity, then spills to the heap.
2//!
3//! [`SmallVec<T, N>`] behaves like `Vec<T>` but keeps up to `N` elements on the stack.
4//! When more than `N` elements are needed, data is moved to a heap-allocated `Vec<T>`.
5//!
6//! This is useful when the common case fits in a small, fixed buffer but you still need
7//! to handle occasional overflow without panicking.
8//!
9//! # Examples
10//!
11//! ```
12//! use planck_noalloc::smallvec::SmallVec;
13//!
14//! let mut sv = SmallVec::<i32, 4>::new();
15//! sv.push(1);
16//! sv.push(2);
17//! sv.push(3);
18//! assert!(sv.is_inline());
19//! assert_eq!(sv.as_slice(), &[1, 2, 3]);
20//!
21//! // Push beyond inline capacity — spills to heap
22//! sv.push(4);
23//! sv.push(5);
24//! assert!(!sv.is_inline());
25//! assert_eq!(sv.as_slice(), &[1, 2, 3, 4, 5]);
26//! ```
27
28use alloc::vec::Vec;
29use core::mem::MaybeUninit;
30
31/// Internal representation: either inline or heap-allocated.
32enum Repr<T, const N: usize> {
33    Inline {
34        data: [MaybeUninit<T>; N],
35        len: usize,
36    },
37    Heap(Vec<T>),
38}
39
40/// A vector that stores up to `N` elements inline on the stack, spilling to the heap
41/// when capacity is exceeded.
42///
43/// # Type Parameters
44///
45/// - `T`: The element type
46/// - `N`: The inline capacity (number of elements stored on the stack)
47pub struct SmallVec<T, const N: usize> {
48    repr: Repr<T, N>,
49}
50
51impl<T, const N: usize> SmallVec<T, N> {
52    /// Creates a new, empty `SmallVec`.
53    #[must_use]
54    pub const fn new() -> Self {
55        Self {
56            repr: Repr::Inline {
57                data: [const { MaybeUninit::uninit() }; N],
58                len: 0,
59            },
60        }
61    }
62
63    /// Creates a new `SmallVec` with at least the specified capacity.
64    ///
65    /// If `cap <= N`, the data stays inline. Otherwise, a heap `Vec` is allocated.
66    #[must_use]
67    pub fn with_capacity(cap: usize) -> Self {
68        if cap <= N {
69            Self::new()
70        } else {
71            Self {
72                repr: Repr::Heap(Vec::with_capacity(cap)),
73            }
74        }
75    }
76
77    /// Returns the number of elements.
78    #[must_use]
79    pub fn len(&self) -> usize {
80        match &self.repr {
81            Repr::Inline { len, .. } => *len,
82            Repr::Heap(v) => v.len(),
83        }
84    }
85
86    /// Returns `true` if the vector is empty.
87    #[must_use]
88    pub fn is_empty(&self) -> bool {
89        self.len() == 0
90    }
91
92    /// Returns the current capacity.
93    #[must_use]
94    pub fn capacity(&self) -> usize {
95        match &self.repr {
96            Repr::Inline { .. } => N,
97            Repr::Heap(v) => v.capacity(),
98        }
99    }
100
101    /// Returns `true` if elements are stored inline (not on the heap).
102    #[must_use]
103    pub fn is_inline(&self) -> bool {
104        matches!(self.repr, Repr::Inline { .. })
105    }
106
107    /// Returns a slice of all elements.
108    #[must_use]
109    pub fn as_slice(&self) -> &[T] {
110        match &self.repr {
111            Repr::Inline { data, len } => {
112                // SAFETY: Elements 0..*len are initialized.
113                unsafe { core::slice::from_raw_parts(data.as_ptr().cast::<T>(), *len) }
114            }
115            Repr::Heap(v) => v.as_slice(),
116        }
117    }
118
119    /// Returns a mutable slice of all elements.
120    #[must_use]
121    pub fn as_mut_slice(&mut self) -> &mut [T] {
122        match &mut self.repr {
123            Repr::Inline { data, len } => {
124                // SAFETY: Elements 0..*len are initialized.
125                unsafe { core::slice::from_raw_parts_mut(data.as_mut_ptr().cast::<T>(), *len) }
126            }
127            Repr::Heap(v) => v.as_mut_slice(),
128        }
129    }
130
131    /// Returns a pointer to the first element.
132    #[must_use]
133    pub fn as_ptr(&self) -> *const T {
134        match &self.repr {
135            Repr::Inline { data, .. } => data.as_ptr().cast::<T>(),
136            Repr::Heap(v) => v.as_ptr(),
137        }
138    }
139
140    /// Returns a mutable pointer to the first element.
141    #[must_use]
142    pub fn as_mut_ptr(&mut self) -> *mut T {
143        match &mut self.repr {
144            Repr::Inline { data, .. } => data.as_mut_ptr().cast::<T>(),
145            Repr::Heap(v) => v.as_mut_ptr(),
146        }
147    }
148
149    /// Appends an element.
150    ///
151    /// If the inline buffer is full, spills to the heap.
152    pub fn push(&mut self, value: T) {
153        match &mut self.repr {
154            Repr::Inline { data, len } if *len < N => {
155                data[*len].write(value);
156                *len += 1;
157            }
158            _ => {
159                self.spill_and_push(value);
160            }
161        }
162    }
163
164    /// Spills inline data to the heap (if needed) and pushes the value.
165    fn spill_and_push(&mut self, value: T) {
166        match &mut self.repr {
167            Repr::Heap(v) => {
168                v.push(value);
169            }
170            Repr::Inline { .. } => {
171                self.spill();
172                if let Repr::Heap(v) = &mut self.repr {
173                    v.push(value);
174                }
175            }
176        }
177    }
178
179    /// Removes and returns the last element, or `None` if empty.
180    #[must_use]
181    pub fn pop(&mut self) -> Option<T> {
182        match &mut self.repr {
183            Repr::Inline { data, len } => {
184                if *len == 0 {
185                    return None;
186                }
187                *len -= 1;
188                // SAFETY: Element at *len was initialized.
189                Some(unsafe { data[*len].assume_init_read() })
190            }
191            Repr::Heap(v) => v.pop(),
192        }
193    }
194
195    /// Inserts an element at `index`, shifting elements after it to the right.
196    ///
197    /// # Panics
198    ///
199    /// Panics if `index > len`.
200    pub fn insert(&mut self, index: usize, value: T) {
201        let len = self.len();
202        assert!(index <= len, "index out of bounds");
203
204        if let Repr::Inline { .. } = &self.repr {
205            if len >= N {
206                self.spill();
207            }
208        }
209
210        match &mut self.repr {
211            Repr::Inline { data, len } => {
212                // SAFETY: We shift elements [index..*len] one position right.
213                unsafe {
214                    let ptr = data.as_mut_ptr().add(index);
215                    core::ptr::copy(ptr, ptr.add(1), *len - index);
216                    ptr.cast::<T>().write(value);
217                }
218                *len += 1;
219            }
220            Repr::Heap(v) => v.insert(index, value),
221        }
222    }
223
224    /// Removes and returns the element at `index`, shifting elements after it left.
225    ///
226    /// # Panics
227    ///
228    /// Panics if `index >= len`.
229    pub fn remove(&mut self, index: usize) -> T {
230        let len = self.len();
231        assert!(index < len, "index out of bounds");
232
233        match &mut self.repr {
234            Repr::Inline { data, len } => {
235                // SAFETY: Element at `index` is initialized. We read it, then
236                // shift elements [index+1..*len] one position left.
237                unsafe {
238                    let ptr = data.as_mut_ptr().add(index);
239                    let value = ptr.cast::<T>().read();
240                    core::ptr::copy(ptr.add(1), ptr, *len - index - 1);
241                    *len -= 1;
242                    value
243                }
244            }
245            Repr::Heap(v) => v.remove(index),
246        }
247    }
248
249    /// Removes the element at `index` by swapping it with the last element.
250    /// Does not preserve ordering but is O(1).
251    ///
252    /// # Panics
253    ///
254    /// Panics if `index >= len`.
255    pub fn swap_remove(&mut self, index: usize) -> T {
256        let len = self.len();
257        assert!(index < len, "index out of bounds");
258
259        match &mut self.repr {
260            Repr::Inline { data, len } => {
261                *len -= 1;
262                data.swap(index, *len);
263                // SAFETY: The element (now at *len) was initialized.
264                unsafe { data[*len].assume_init_read() }
265            }
266            Repr::Heap(v) => v.swap_remove(index),
267        }
268    }
269
270    /// Removes all elements.
271    pub fn clear(&mut self) {
272        match &mut self.repr {
273            Repr::Inline { data, len } => {
274                for item in data.iter_mut().take(*len) {
275                    // SAFETY: Elements 0..*len are initialized.
276                    unsafe {
277                        item.assume_init_drop();
278                    }
279                }
280                *len = 0;
281            }
282            Repr::Heap(v) => v.clear(),
283        }
284    }
285
286    /// Truncates the vector to at most `new_len` elements.
287    ///
288    /// If `new_len >= len`, this is a no-op.
289    pub fn truncate(&mut self, new_len: usize) {
290        let len = self.len();
291        if new_len >= len {
292            return;
293        }
294
295        match &mut self.repr {
296            Repr::Inline { data, len } => {
297                for item in data.iter_mut().take(*len).skip(new_len) {
298                    // SAFETY: Elements new_len..*len are initialized.
299                    unsafe {
300                        item.assume_init_drop();
301                    }
302                }
303                *len = new_len;
304            }
305            Repr::Heap(v) => v.truncate(new_len),
306        }
307    }
308
309    /// Returns a reference to the last element, or `None` if empty.
310    #[must_use]
311    pub fn last(&self) -> Option<&T> {
312        let len = self.len();
313        if len == 0 {
314            None
315        } else {
316            Some(&self.as_slice()[len - 1])
317        }
318    }
319
320    /// Returns a mutable reference to the last element, or `None` if empty.
321    #[must_use]
322    pub fn last_mut(&mut self) -> Option<&mut T> {
323        let len = self.len();
324        if len == 0 {
325            None
326        } else {
327            Some(&mut self.as_mut_slice()[len - 1])
328        }
329    }
330
331    /// Reserves capacity for at least `additional` more elements.
332    ///
333    /// If inline and the total needed exceeds `N`, spills to the heap.
334    pub fn reserve(&mut self, additional: usize) {
335        let needed = self.len() + additional;
336        if needed <= self.capacity() {
337            return;
338        }
339
340        match &self.repr {
341            Repr::Inline { .. } => {
342                self.spill_with_capacity(needed);
343            }
344            Repr::Heap(_) => {
345                // Take ownership temporarily
346                let old = core::mem::replace(&mut self.repr, Repr::Inline {
347                    data: [const { MaybeUninit::uninit() }; N],
348                    len: 0,
349                });
350                if let Repr::Heap(mut v) = old {
351                    v.reserve(additional);
352                    self.repr = Repr::Heap(v);
353                }
354            }
355        }
356    }
357
358    /// Moves inline data to a heap `Vec` if currently inline.
359    ///
360    /// No-op if already on the heap.
361    pub fn spill(&mut self) {
362        if let Repr::Inline { len, .. } = &self.repr {
363            let cap = core::cmp::max(2 * N, *len);
364            self.spill_with_capacity(cap);
365        }
366    }
367
368    /// Spills inline data to a heap `Vec` with the given capacity.
369    fn spill_with_capacity(&mut self, cap: usize) {
370        let old = core::mem::replace(
371            &mut self.repr,
372            Repr::Inline {
373                data: [const { MaybeUninit::uninit() }; N],
374                len: 0,
375            },
376        );
377
378        if let Repr::Inline { data, len } = old {
379            let mut v = Vec::with_capacity(cap);
380            // SAFETY: Elements 0..len are initialized. We copy them into the Vec
381            // and set its length. MaybeUninit does not drop its contents, so the
382            // old array being dropped is safe — no double-free occurs.
383            unsafe {
384                core::ptr::copy_nonoverlapping(data.as_ptr().cast::<T>(), v.as_mut_ptr(), len);
385                v.set_len(len);
386            }
387            self.repr = Repr::Heap(v);
388        }
389    }
390
391    /// Shrinks the backing allocation to fit the current length.
392    ///
393    /// If on the heap and `len <= N`, moves data back inline.
394    pub fn shrink_to_fit(&mut self) {
395        if let Repr::Heap(_) = &self.repr {
396            let len = self.len();
397            if len <= N {
398                let old = core::mem::replace(
399                    &mut self.repr,
400                    Repr::Inline {
401                        data: [const { MaybeUninit::uninit() }; N],
402                        len: 0,
403                    },
404                );
405                if let Repr::Heap(v) = old {
406                    let mut data = [const { MaybeUninit::uninit() }; N];
407                    // SAFETY: We copy len elements from the Vec into the inline array.
408                    unsafe {
409                        core::ptr::copy_nonoverlapping(
410                            v.as_ptr(),
411                            data.as_mut_ptr().cast::<T>(),
412                            len,
413                        );
414                    }
415                    // Forget Vec so elements aren't double-dropped; we own them in `data` now.
416                    // We need to drop the Vec without dropping elements. Use set_len(0) then drop.
417                    let mut v = v;
418                    // SAFETY: Setting len to 0 before drop prevents element drops.
419                    unsafe {
420                        v.set_len(0);
421                    }
422                    drop(v);
423                    self.repr = Repr::Inline { data, len };
424                }
425            } else {
426                // Still on heap, just shrink the Vec
427                let old = core::mem::replace(
428                    &mut self.repr,
429                    Repr::Inline {
430                        data: [const { MaybeUninit::uninit() }; N],
431                        len: 0,
432                    },
433                );
434                if let Repr::Heap(mut v) = old {
435                    v.shrink_to_fit();
436                    self.repr = Repr::Heap(v);
437                }
438            }
439        }
440    }
441
442    /// Returns an iterator over references to elements.
443    pub fn iter(&self) -> core::slice::Iter<'_, T> {
444        self.as_slice().iter()
445    }
446
447    /// Returns an iterator over mutable references to elements.
448    pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, T> {
449        self.as_mut_slice().iter_mut()
450    }
451
452    /// Converts this `SmallVec` into a heap-allocated `Vec<T>`.
453    #[must_use]
454    pub fn into_vec(mut self) -> Vec<T> {
455        self.spill();
456        let old = core::mem::replace(
457            &mut self.repr,
458            Repr::Inline {
459                data: [const { MaybeUninit::uninit() }; N],
460                len: 0,
461            },
462        );
463        match old {
464            Repr::Heap(v) => v,
465            Repr::Inline { .. } => unreachable!(),
466        }
467    }
468}
469
470impl<T: Clone, const N: usize> Clone for SmallVec<T, N> {
471    fn clone(&self) -> Self {
472        match &self.repr {
473            Repr::Inline { data, len } => {
474                let mut new_data = [const { MaybeUninit::uninit() }; N];
475                for i in 0..*len {
476                    // SAFETY: Elements 0..*len are initialized.
477                    new_data[i].write(unsafe { data[i].assume_init_ref() }.clone());
478                }
479                Self {
480                    repr: Repr::Inline {
481                        data: new_data,
482                        len: *len,
483                    },
484                }
485            }
486            Repr::Heap(v) => Self {
487                repr: Repr::Heap(v.clone()),
488            },
489        }
490    }
491}
492
493impl<T: core::fmt::Debug, const N: usize> core::fmt::Debug for SmallVec<T, N> {
494    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
495        f.debug_list().entries(self.as_slice()).finish()
496    }
497}
498
499impl<T, const N: usize> Default for SmallVec<T, N> {
500    fn default() -> Self {
501        Self::new()
502    }
503}
504
505impl<T, const N: usize> Drop for SmallVec<T, N> {
506    fn drop(&mut self) {
507        if let Repr::Inline { data, len } = &mut self.repr {
508            for item in data.iter_mut().take(*len) {
509                // SAFETY: Elements 0..*len are initialized.
510                unsafe {
511                    item.assume_init_drop();
512                }
513            }
514            *len = 0;
515        }
516        // Repr::Heap(Vec) is dropped automatically.
517    }
518}
519
520impl<T: PartialEq, const N: usize> PartialEq for SmallVec<T, N> {
521    fn eq(&self, other: &Self) -> bool {
522        self.as_slice() == other.as_slice()
523    }
524}
525
526impl<T: Eq, const N: usize> Eq for SmallVec<T, N> {}
527
528impl<T: core::hash::Hash, const N: usize> core::hash::Hash for SmallVec<T, N> {
529    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
530        self.as_slice().hash(state);
531    }
532}
533
534impl<T: PartialOrd, const N: usize> PartialOrd for SmallVec<T, N> {
535    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
536        self.as_slice().partial_cmp(other.as_slice())
537    }
538}
539
540impl<T: Ord, const N: usize> Ord for SmallVec<T, N> {
541    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
542        self.as_slice().cmp(other.as_slice())
543    }
544}
545
546impl<T, const N: usize> core::ops::Deref for SmallVec<T, N> {
547    type Target = [T];
548
549    fn deref(&self) -> &[T] {
550        self.as_slice()
551    }
552}
553
554impl<T, const N: usize> core::ops::DerefMut for SmallVec<T, N> {
555    fn deref_mut(&mut self) -> &mut [T] {
556        self.as_mut_slice()
557    }
558}
559
560impl<T, const N: usize> core::ops::Index<usize> for SmallVec<T, N> {
561    type Output = T;
562
563    fn index(&self, index: usize) -> &T {
564        &self.as_slice()[index]
565    }
566}
567
568impl<T, const N: usize> core::ops::IndexMut<usize> for SmallVec<T, N> {
569    fn index_mut(&mut self, index: usize) -> &mut T {
570        &mut self.as_mut_slice()[index]
571    }
572}
573
574impl<T, const N: usize> From<Vec<T>> for SmallVec<T, N> {
575    fn from(v: Vec<T>) -> Self {
576        Self {
577            repr: Repr::Heap(v),
578        }
579    }
580}
581
582impl<T: Clone, const N: usize> From<&[T]> for SmallVec<T, N> {
583    fn from(slice: &[T]) -> Self {
584        let mut sv = Self::with_capacity(slice.len());
585        for item in slice {
586            sv.push(item.clone());
587        }
588        sv
589    }
590}
591
592impl<T, const N: usize> From<[T; N]> for SmallVec<T, N> {
593    fn from(array: [T; N]) -> Self {
594        let mut data: [MaybeUninit<T>; N] = [const { MaybeUninit::uninit() }; N];
595        // SAFETY: We move each element from the array into MaybeUninit slots.
596        // We read from the array via raw pointer, then forget the array to avoid
597        // double-drop. MaybeUninit slots now own the values.
598        unsafe {
599            let src: *const T = (&raw const array).cast::<T>();
600            for (i, slot) in data.iter_mut().enumerate().take(N) {
601                slot.write(src.add(i).read());
602            }
603            core::mem::forget(array);
604        }
605        Self {
606            repr: Repr::Inline { data, len: N },
607        }
608    }
609}
610
611impl<T, const N: usize> AsRef<[T]> for SmallVec<T, N> {
612    fn as_ref(&self) -> &[T] {
613        self.as_slice()
614    }
615}
616
617impl<T, const N: usize> AsMut<[T]> for SmallVec<T, N> {
618    fn as_mut(&mut self) -> &mut [T] {
619        self.as_mut_slice()
620    }
621}
622
623impl<T, const N: usize> core::borrow::Borrow<[T]> for SmallVec<T, N> {
624    fn borrow(&self) -> &[T] {
625        self.as_slice()
626    }
627}
628
629impl<T, const N: usize> core::borrow::BorrowMut<[T]> for SmallVec<T, N> {
630    fn borrow_mut(&mut self) -> &mut [T] {
631        self.as_mut_slice()
632    }
633}
634
635impl<T, const N: usize> Extend<T> for SmallVec<T, N> {
636    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
637        for item in iter {
638            self.push(item);
639        }
640    }
641}
642
643impl<T, const N: usize> FromIterator<T> for SmallVec<T, N> {
644    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
645        let mut sv = Self::new();
646        sv.extend(iter);
647        sv
648    }
649}
650
651// --- IntoIterator (owning) ---
652
653/// Owning iterator over a [`SmallVec`].
654pub struct SmallVecIntoIter<T, const N: usize> {
655    inner: IntoIterRepr<T, N>,
656}
657
658enum IntoIterRepr<T, const N: usize> {
659    Inline {
660        data: [MaybeUninit<T>; N],
661        start: usize,
662        end: usize,
663    },
664    Heap(alloc::vec::IntoIter<T>),
665}
666
667impl<T, const N: usize> Iterator for SmallVecIntoIter<T, N> {
668    type Item = T;
669
670    fn next(&mut self) -> Option<T> {
671        match &mut self.inner {
672            IntoIterRepr::Inline { data, start, end } => {
673                if *start >= *end {
674                    return None;
675                }
676                let idx = *start;
677                *start += 1;
678                // SAFETY: Elements start..end are initialized.
679                Some(unsafe { data[idx].assume_init_read() })
680            }
681            IntoIterRepr::Heap(iter) => iter.next(),
682        }
683    }
684
685    fn size_hint(&self) -> (usize, Option<usize>) {
686        let remaining = self.len();
687        (remaining, Some(remaining))
688    }
689}
690
691impl<T, const N: usize> DoubleEndedIterator for SmallVecIntoIter<T, N> {
692    fn next_back(&mut self) -> Option<T> {
693        match &mut self.inner {
694            IntoIterRepr::Inline { data, start, end } => {
695                if *start >= *end {
696                    return None;
697                }
698                *end -= 1;
699                // SAFETY: Elements start..end are initialized.
700                Some(unsafe { data[*end].assume_init_read() })
701            }
702            IntoIterRepr::Heap(iter) => iter.next_back(),
703        }
704    }
705}
706
707impl<T, const N: usize> ExactSizeIterator for SmallVecIntoIter<T, N> {
708    fn len(&self) -> usize {
709        match &self.inner {
710            IntoIterRepr::Inline { start, end, .. } => *end - *start,
711            IntoIterRepr::Heap(iter) => iter.len(),
712        }
713    }
714}
715
716impl<T, const N: usize> Drop for SmallVecIntoIter<T, N> {
717    fn drop(&mut self) {
718        // Drop remaining elements that haven't been consumed.
719        if let IntoIterRepr::Inline { data, start, end } = &mut self.inner {
720            for item in data.iter_mut().take(*end).skip(*start) {
721                // SAFETY: Elements start..end are still initialized.
722                unsafe {
723                    item.assume_init_drop();
724                }
725            }
726            *start = *end;
727        }
728        // Heap variant: alloc::vec::IntoIter handles its own drop.
729    }
730}
731
732impl<T, const N: usize> IntoIterator for SmallVec<T, N> {
733    type Item = T;
734    type IntoIter = SmallVecIntoIter<T, N>;
735
736    fn into_iter(mut self) -> SmallVecIntoIter<T, N> {
737        let inner = match &mut self.repr {
738            Repr::Inline { len, .. } => {
739                let end = *len;
740                // Take ownership of the data array by replacing repr.
741                // Set len to 0 so Drop doesn't double-drop.
742                *len = 0;
743                let old = core::mem::replace(
744                    &mut self.repr,
745                    Repr::Inline {
746                        data: [const { MaybeUninit::uninit() }; N],
747                        len: 0,
748                    },
749                );
750                match old {
751                    Repr::Inline { data, .. } => IntoIterRepr::Inline {
752                        data,
753                        start: 0,
754                        end,
755                    },
756                    Repr::Heap(_) => unreachable!(),
757                }
758            }
759            Repr::Heap(_) => {
760                let old = core::mem::replace(
761                    &mut self.repr,
762                    Repr::Inline {
763                        data: [const { MaybeUninit::uninit() }; N],
764                        len: 0,
765                    },
766                );
767                match old {
768                    Repr::Heap(v) => IntoIterRepr::Heap(v.into_iter()),
769                    Repr::Inline { .. } => unreachable!(),
770                }
771            }
772        };
773        // self.repr is now an empty Inline, so Drop does nothing.
774        SmallVecIntoIter { inner }
775    }
776}
777
778impl<'a, T, const N: usize> IntoIterator for &'a SmallVec<T, N> {
779    type Item = &'a T;
780    type IntoIter = core::slice::Iter<'a, T>;
781
782    fn into_iter(self) -> Self::IntoIter {
783        self.iter()
784    }
785}
786
787impl<'a, T, const N: usize> IntoIterator for &'a mut SmallVec<T, N> {
788    type Item = &'a mut T;
789    type IntoIter = core::slice::IterMut<'a, T>;
790
791    fn into_iter(self) -> Self::IntoIter {
792        self.iter_mut()
793    }
794}
795
796#[cfg(test)]
797mod tests {
798    extern crate alloc;
799    use alloc::string::String;
800    use alloc::vec;
801
802    use super::*;
803
804    #[test]
805    fn new_is_empty() {
806        let sv = SmallVec::<i32, 4>::new();
807        assert!(sv.is_empty());
808        assert_eq!(sv.len(), 0);
809        assert!(sv.is_inline());
810    }
811
812    #[test]
813    fn push_within_capacity() {
814        let mut sv = SmallVec::<i32, 4>::new();
815        sv.push(1);
816        sv.push(2);
817        sv.push(3);
818        assert_eq!(sv.len(), 3);
819        assert!(sv.is_inline());
820        assert_eq!(sv.as_slice(), &[1, 2, 3]);
821    }
822
823    #[test]
824    fn push_spills_to_heap() {
825        let mut sv = SmallVec::<i32, 2>::new();
826        sv.push(1);
827        sv.push(2);
828        assert!(sv.is_inline());
829        sv.push(3);
830        assert!(!sv.is_inline());
831        assert_eq!(sv.as_slice(), &[1, 2, 3]);
832    }
833
834    #[test]
835    fn pop_inline() {
836        let mut sv = SmallVec::<i32, 4>::new();
837        sv.push(10);
838        sv.push(20);
839        assert_eq!(sv.pop(), Some(20));
840        assert_eq!(sv.pop(), Some(10));
841        assert_eq!(sv.pop(), None);
842    }
843
844    #[test]
845    fn pop_heap() {
846        let mut sv = SmallVec::<i32, 1>::new();
847        sv.push(1);
848        sv.push(2);
849        sv.push(3);
850        assert_eq!(sv.pop(), Some(3));
851        assert_eq!(sv.pop(), Some(2));
852        assert_eq!(sv.pop(), Some(1));
853        assert_eq!(sv.pop(), None);
854    }
855
856    #[test]
857    fn insert_inline() {
858        let mut sv = SmallVec::<i32, 4>::new();
859        sv.push(1);
860        sv.push(3);
861        sv.insert(1, 2);
862        assert_eq!(sv.as_slice(), &[1, 2, 3]);
863        assert!(sv.is_inline());
864    }
865
866    #[test]
867    fn insert_causes_spill() {
868        let mut sv = SmallVec::<i32, 2>::new();
869        sv.push(1);
870        sv.push(3);
871        sv.insert(1, 2);
872        assert_eq!(sv.as_slice(), &[1, 2, 3]);
873        assert!(!sv.is_inline());
874    }
875
876    #[test]
877    fn remove_inline() {
878        let mut sv = SmallVec::<i32, 4>::new();
879        sv.push(1);
880        sv.push(2);
881        sv.push(3);
882        let removed = sv.remove(1);
883        assert_eq!(removed, 2);
884        assert_eq!(sv.as_slice(), &[1, 3]);
885    }
886
887    #[test]
888    fn swap_remove_inline() {
889        let mut sv = SmallVec::<i32, 4>::new();
890        sv.push(10);
891        sv.push(20);
892        sv.push(30);
893        let removed = sv.swap_remove(0);
894        assert_eq!(removed, 10);
895        assert_eq!(sv.as_slice(), &[30, 20]);
896    }
897
898    #[test]
899    fn clear_inline() {
900        let mut sv = SmallVec::<i32, 4>::new();
901        sv.push(1);
902        sv.push(2);
903        sv.clear();
904        assert!(sv.is_empty());
905    }
906
907    #[test]
908    fn clear_heap() {
909        let mut sv = SmallVec::<i32, 1>::new();
910        sv.push(1);
911        sv.push(2);
912        sv.push(3);
913        sv.clear();
914        assert!(sv.is_empty());
915    }
916
917    #[test]
918    fn truncate_inline() {
919        let mut sv = SmallVec::<i32, 4>::new();
920        sv.push(1);
921        sv.push(2);
922        sv.push(3);
923        sv.truncate(1);
924        assert_eq!(sv.as_slice(), &[1]);
925    }
926
927    #[test]
928    fn truncate_noop() {
929        let mut sv = SmallVec::<i32, 4>::new();
930        sv.push(1);
931        sv.truncate(5);
932        assert_eq!(sv.len(), 1);
933    }
934
935    #[test]
936    fn last_and_last_mut() {
937        let mut sv = SmallVec::<i32, 4>::new();
938        assert_eq!(sv.last(), None);
939        sv.push(1);
940        sv.push(2);
941        assert_eq!(sv.last(), Some(&2));
942        *sv.last_mut().unwrap() = 99;
943        assert_eq!(sv.last(), Some(&99));
944    }
945
946    #[test]
947    fn capacity_inline() {
948        let sv = SmallVec::<i32, 4>::new();
949        assert_eq!(sv.capacity(), 4);
950    }
951
952    #[test]
953    fn with_capacity_inline() {
954        let sv = SmallVec::<i32, 4>::with_capacity(3);
955        assert!(sv.is_inline());
956        assert_eq!(sv.capacity(), 4);
957    }
958
959    #[test]
960    fn with_capacity_heap() {
961        let sv = SmallVec::<i32, 4>::with_capacity(10);
962        assert!(!sv.is_inline());
963        assert!(sv.capacity() >= 10);
964    }
965
966    #[test]
967    fn reserve_spills() {
968        let mut sv = SmallVec::<i32, 2>::new();
969        sv.push(1);
970        sv.reserve(5);
971        assert!(!sv.is_inline());
972        assert!(sv.capacity() >= 6);
973        assert_eq!(sv.as_slice(), &[1]);
974    }
975
976    #[test]
977    fn spill_and_shrink_back() {
978        let mut sv = SmallVec::<i32, 4>::new();
979        sv.push(1);
980        sv.push(2);
981        sv.spill();
982        assert!(!sv.is_inline());
983        assert_eq!(sv.as_slice(), &[1, 2]);
984        sv.shrink_to_fit();
985        assert!(sv.is_inline());
986        assert_eq!(sv.as_slice(), &[1, 2]);
987    }
988
989    #[test]
990    fn clone_inline() {
991        let mut sv = SmallVec::<i32, 4>::new();
992        sv.push(1);
993        sv.push(2);
994        let sv2 = sv.clone();
995        assert_eq!(sv2.as_slice(), &[1, 2]);
996        assert!(sv2.is_inline());
997    }
998
999    #[test]
1000    fn clone_heap() {
1001        let mut sv = SmallVec::<i32, 1>::new();
1002        sv.push(1);
1003        sv.push(2);
1004        let sv2 = sv.clone();
1005        assert_eq!(sv2.as_slice(), &[1, 2]);
1006    }
1007
1008    #[test]
1009    fn debug_format() {
1010        let mut sv = SmallVec::<i32, 4>::new();
1011        sv.push(1);
1012        sv.push(2);
1013        let s = alloc::format!("{sv:?}");
1014        assert_eq!(s, "[1, 2]");
1015    }
1016
1017    #[test]
1018    fn eq_and_ord() {
1019        let mut a = SmallVec::<i32, 4>::new();
1020        a.push(1);
1021        a.push(2);
1022        let mut b = SmallVec::<i32, 4>::new();
1023        b.push(1);
1024        b.push(2);
1025        assert_eq!(a, b);
1026
1027        let mut c = SmallVec::<i32, 4>::new();
1028        c.push(1);
1029        c.push(3);
1030        assert!(a < c);
1031    }
1032
1033    #[test]
1034    fn index_and_index_mut() {
1035        let mut sv = SmallVec::<i32, 4>::new();
1036        sv.push(10);
1037        sv.push(20);
1038        assert_eq!(sv[0], 10);
1039        sv[0] = 99;
1040        assert_eq!(sv[0], 99);
1041    }
1042
1043    #[test]
1044    fn from_vec() {
1045        let sv: SmallVec<i32, 4> = SmallVec::from(vec![1, 2, 3]);
1046        assert!(!sv.is_inline());
1047        assert_eq!(sv.as_slice(), &[1, 2, 3]);
1048    }
1049
1050    #[test]
1051    fn from_slice() {
1052        let sv: SmallVec<i32, 4> = SmallVec::from([1, 2, 3].as_slice());
1053        assert!(sv.is_inline());
1054        assert_eq!(sv.as_slice(), &[1, 2, 3]);
1055    }
1056
1057    #[test]
1058    fn from_array() {
1059        let sv: SmallVec<i32, 3> = SmallVec::from([1, 2, 3]);
1060        assert!(sv.is_inline());
1061        assert_eq!(sv.as_slice(), &[1, 2, 3]);
1062    }
1063
1064    #[test]
1065    fn extend_and_from_iter() {
1066        let sv: SmallVec<i32, 2> = (0..5).collect();
1067        assert_eq!(sv.as_slice(), &[0, 1, 2, 3, 4]);
1068    }
1069
1070    #[test]
1071    fn into_iter_inline() {
1072        let mut sv = SmallVec::<i32, 4>::new();
1073        sv.push(1);
1074        sv.push(2);
1075        sv.push(3);
1076        let collected: Vec<i32> = sv.into_iter().collect();
1077        assert_eq!(collected, vec![1, 2, 3]);
1078    }
1079
1080    #[test]
1081    fn into_iter_heap() {
1082        let mut sv = SmallVec::<i32, 1>::new();
1083        sv.push(1);
1084        sv.push(2);
1085        sv.push(3);
1086        let collected: Vec<i32> = sv.into_iter().collect();
1087        assert_eq!(collected, vec![1, 2, 3]);
1088    }
1089
1090    #[test]
1091    fn into_iter_double_ended() {
1092        let mut sv = SmallVec::<i32, 4>::new();
1093        sv.push(1);
1094        sv.push(2);
1095        sv.push(3);
1096        let collected: Vec<i32> = sv.into_iter().rev().collect();
1097        assert_eq!(collected, vec![3, 2, 1]);
1098    }
1099
1100    #[test]
1101    fn into_iter_exact_size() {
1102        let mut sv = SmallVec::<i32, 4>::new();
1103        sv.push(1);
1104        sv.push(2);
1105        let mut iter = sv.into_iter();
1106        assert_eq!(iter.len(), 2);
1107        iter.next();
1108        assert_eq!(iter.len(), 1);
1109    }
1110
1111    #[test]
1112    fn into_vec_conversion() {
1113        let mut sv = SmallVec::<i32, 4>::new();
1114        sv.push(1);
1115        sv.push(2);
1116        let v = sv.into_vec();
1117        assert_eq!(v, vec![1, 2]);
1118    }
1119
1120    #[test]
1121    fn drop_elements_properly() {
1122        use alloc::rc::Rc;
1123        let rc = Rc::new(());
1124        let mut sv = SmallVec::<Rc<()>, 2>::new();
1125        sv.push(rc.clone());
1126        sv.push(rc.clone());
1127        assert_eq!(Rc::strong_count(&rc), 3);
1128        drop(sv);
1129        assert_eq!(Rc::strong_count(&rc), 1);
1130    }
1131
1132    #[test]
1133    fn drop_elements_on_heap() {
1134        use alloc::rc::Rc;
1135        let rc = Rc::new(());
1136        let mut sv = SmallVec::<Rc<()>, 1>::new();
1137        sv.push(rc.clone());
1138        sv.push(rc.clone());
1139        sv.push(rc.clone());
1140        assert_eq!(Rc::strong_count(&rc), 4);
1141        drop(sv);
1142        assert_eq!(Rc::strong_count(&rc), 1);
1143    }
1144
1145    #[test]
1146    fn into_iter_drops_remaining() {
1147        use alloc::rc::Rc;
1148        let rc = Rc::new(());
1149        let mut sv = SmallVec::<Rc<()>, 4>::new();
1150        sv.push(rc.clone());
1151        sv.push(rc.clone());
1152        sv.push(rc.clone());
1153        let mut iter = sv.into_iter();
1154        iter.next(); // consume one
1155        assert_eq!(Rc::strong_count(&rc), 3); // 1 original + 2 remaining in iter
1156        drop(iter);
1157        assert_eq!(Rc::strong_count(&rc), 1);
1158    }
1159
1160    #[test]
1161    fn as_ref_as_mut_borrow() {
1162        let mut sv = SmallVec::<i32, 4>::new();
1163        sv.push(1);
1164        sv.push(2);
1165        let r: &[i32] = sv.as_ref();
1166        assert_eq!(r, &[1, 2]);
1167        let m: &mut [i32] = sv.as_mut();
1168        m[0] = 99;
1169        assert_eq!(sv[0], 99);
1170    }
1171
1172    #[test]
1173    fn deref_and_deref_mut() {
1174        let mut sv = SmallVec::<i32, 4>::new();
1175        sv.push(3);
1176        sv.push(1);
1177        sv.push(2);
1178        // Deref to &[T] gives us slice methods
1179        assert!(sv.contains(&1));
1180        // DerefMut to &mut [T]
1181        sv.sort();
1182        assert_eq!(&*sv, &[1, 2, 3]);
1183    }
1184
1185    #[test]
1186    fn hash_consistent() {
1187        use core::hash::{Hash, Hasher};
1188
1189        struct SimpleHasher(u64);
1190        impl Hasher for SimpleHasher {
1191            fn finish(&self) -> u64 {
1192                self.0
1193            }
1194            fn write(&mut self, bytes: &[u8]) {
1195                for &b in bytes {
1196                    self.0 = self.0.wrapping_mul(31).wrapping_add(u64::from(b));
1197                }
1198            }
1199        }
1200
1201        let mut a = SmallVec::<i32, 4>::new();
1202        a.push(1);
1203        a.push(2);
1204
1205        let mut b = SmallVec::<i32, 4>::new();
1206        b.push(1);
1207        b.push(2);
1208
1209        let mut ha = SimpleHasher(0);
1210        let mut hb = SimpleHasher(0);
1211        a.hash(&mut ha);
1212        b.hash(&mut hb);
1213        assert_eq!(ha.finish(), hb.finish());
1214    }
1215
1216    #[test]
1217    fn spill_with_drop_types() {
1218        let mut sv = SmallVec::<String, 2>::new();
1219        sv.push(String::from("hello"));
1220        sv.push(String::from("world"));
1221        sv.spill();
1222        assert!(!sv.is_inline());
1223        assert_eq!(sv.as_slice(), &["hello", "world"]);
1224    }
1225
1226    #[test]
1227    fn shrink_to_fit_stays_heap_when_too_large() {
1228        let mut sv = SmallVec::<i32, 2>::new();
1229        for i in 0..10 {
1230            sv.push(i);
1231        }
1232        sv.shrink_to_fit();
1233        assert!(!sv.is_inline());
1234        assert_eq!(sv.len(), 10);
1235    }
1236
1237    #[test]
1238    fn zero_inline_capacity() {
1239        let mut sv = SmallVec::<i32, 0>::new();
1240        assert!(sv.is_inline());
1241        sv.push(1); // immediately spills
1242        assert!(!sv.is_inline());
1243        assert_eq!(sv.as_slice(), &[1]);
1244    }
1245}