Skip to main content

sharky_arrayvec/
lib.rs

1#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
2#![cfg_attr(
3    feature = "nightly",
4    feature(
5        const_clone,
6        const_trait_impl,
7        const_index,
8        const_default,
9        const_convert,
10        const_destruct,
11        const_drop_in_place,
12        min_specialization,
13        const_cmp,
14    )
15)]
16#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
17
18use core::mem;
19use core::mem::MaybeUninit;
20
21mod iter;
22pub use iter::ArrayVecIter;
23
24#[cfg(feature = "deku")]
25pub mod deku;
26
27#[cfg(feature = "nightly")]
28mod nightly;
29
30#[cfg(not(feature = "nightly"))]
31mod stable;
32
33fn write_filled<T: Clone>(slice: &mut [MaybeUninit<T>], value: T) {
34    if slice.is_empty() {
35        return;
36    }
37
38    let len = slice.len();
39    for elem in &mut slice[..len.saturating_sub(1)] {
40        elem.write(value.clone());
41    }
42    slice[len.saturating_sub(1)].write(value);
43}
44
45const fn ptr_cast_array<const N: usize, T>(ptr: *const T) -> *const [T; N] {
46    ptr.cast()
47}
48
49const fn ptr_cast_array_mut<const N: usize, T>(ptr: *mut T) -> *mut [T; N] {
50    ptr.cast()
51}
52
53/// # Safety
54///
55/// - `Src` and `Dest` **must** have the same invariants. That is, any valid
56///   `Src` must also be a valid `Dest`.
57const unsafe fn reinterpret_array_ref<const N: usize, Src, Dest>(src: &[Src; N]) -> &[Dest; N] {
58    #[expect(clippy::manual_assert)]
59    if size_of::<Src>() != size_of::<Dest>() {
60        panic!("Src and Dest have different sizes");
61    }
62
63    let src_ptr: *const Src = src.as_ptr();
64    let dest_ptr: *const Dest = src_ptr.cast();
65    let dest_array_ptr: *const [Dest; N] = ptr_cast_array(dest_ptr);
66
67    // SAFETY: This is always non-null because it's `src`, but with the reference
68    // cast. While Src and Dest might not have the same invariants, they are the
69    // same size, so there can't be any out-of-bounds accesses.
70    unsafe { dest_array_ptr.as_ref_unchecked() }
71}
72
73/// # Safety
74///
75/// - `Src` and `Dest` **must** have the same invariants. That is, any valid
76///   `Src` must also be a valid `Dest`.
77const unsafe fn reinterpret_array_mut<const N: usize, Src, Dest>(
78    src: &mut [Src; N],
79) -> &mut [Dest; N] {
80    #[expect(clippy::manual_assert)]
81    if size_of::<Src>() != size_of::<Dest>() {
82        panic!("Src and Dest have different sizes");
83    }
84
85    let src_ptr: *mut Src = src.as_mut_ptr();
86    let dest_ptr: *mut Dest = src_ptr.cast();
87    let dest_array_ptr: *mut [Dest; N] = ptr_cast_array_mut(dest_ptr);
88
89    // SAFETY: This is always non-null because it's `src`, but with the reference
90    // cast. While Src and Dest might not have the same invariants, they are the
91    // same size, so there can't be any out-of-bounds accesses.
92    unsafe { dest_array_ptr.as_mut_unchecked() }
93}
94
95// NOTE: This is the stalib's implementation
96const fn slice_shift_right<const N: usize, T>(slice: &mut [T], inserted: [T; N]) -> [T; N] {
97    if let Some(shift) = slice.len().checked_sub(N) {
98        // SAFETY: Having just checked that the inserted/returned arrays are
99        // shorter than (or the same length as) the slice:
100        // 1. The read for the items to return is in-bounds
101        // 2. We can `memmove` the slice over to cover the items we're returning to
102        //    ensure those aren't double-dropped
103        // 3. Then we write (in-bounds for the same reason as the read) the inserted
104        //    items atop the items of the slice that we just duplicated
105        //
106        // And none of this can panic, so there's no risk of intermediate unwinds.
107        unsafe {
108            let ptr = slice.as_mut_ptr();
109            let returned = ptr_cast_array_mut::<N, _>(ptr.add(shift)).read();
110            ptr.add(N).copy_from(ptr, shift);
111            ptr_cast_array_mut::<N, _>(ptr).write(inserted);
112            returned
113        }
114    } else {
115        // SAFETY: Having checked that the slice is strictly shorter than the
116        // inserted/returned arrays, it means we'll be copying the whole slice
117        // into the returned array, but that's not enough on its own.  We also
118        // need to copy some of the inserted array into the returned array,
119        // with the rest going into the slice.  Because `&mut` is exclusive
120        // and we own both `inserted` and `returned`, they're all disjoint
121        // allocations from each other as we can use `nonoverlapping` copies.
122        //
123        // We avoid double-frees by `ManuallyDrop`ing the inserted items,
124        // since we always copy them to other locations that will drop them
125        // instead.  Plus nothing in here can panic -- it's just memcpy three
126        // times -- so there's no intermediate unwinds to worry about.
127        unsafe {
128            let len = slice.len();
129            let slice = slice.as_mut_ptr();
130            let inserted = mem::ManuallyDrop::new(inserted);
131            let inserted = (&raw const inserted).cast::<T>();
132
133            let mut returned = MaybeUninit::<[T; N]>::uninit();
134            let ptr = returned.as_mut_ptr().cast::<T>();
135            ptr.add(N.wrapping_sub(len))
136                .copy_from_nonoverlapping(slice, len);
137            ptr.copy_from_nonoverlapping(inserted.add(len), N.wrapping_sub(len));
138            slice.copy_from_nonoverlapping(inserted, len);
139            returned.assume_init()
140        }
141    }
142}
143
144#[must_use]
145pub struct ArrayVec<const C: usize, T> {
146    array: [MaybeUninit<T>; C],
147    len:   usize,
148}
149
150// NOTE: `BoundedVec` must implement `Drop` because "...dropping a
151// `MaybeUninit<T>` will never call `T`’s drop code. It is your responsibility
152// to make sure `T` gets dropped if it got initialized."
153// See <https://doc.rust-lang.org/std/mem/union.MaybeUninit.html#method.new>
154impl<const C: usize, T> Drop for ArrayVec<C, T> {
155    #[inline]
156    fn drop(&mut self) {
157        for i in 0..self.len {
158            // SAFETY: This is okay because `self.len` tracks the number of initialized
159            // values
160            unsafe { self.array[i].assume_init_drop() };
161        }
162    }
163}
164
165impl<const C: usize, T: Clone> Clone for ArrayVec<C, T> {
166    #[inline]
167    fn clone(&self) -> Self {
168        let mut array = konst::maybe_uninit::UNINIT_ARRAY::<T, C>::V;
169        array[..self.len()].write_clone_of_slice(self.as_slice());
170
171        Self {
172            array,
173            len: self.len,
174        }
175    }
176}
177
178impl<const C: usize, T: core::fmt::Debug> core::fmt::Debug for ArrayVec<C, T> {
179    #[inline]
180    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
181        f.debug_list().entries(self.ref_vec().as_slice()).finish()
182    }
183}
184
185impl<const C: usize, T> ArrayVec<C, T> {
186    pub const CAPACITY: usize = C;
187
188    #[inline]
189    pub const fn new() -> Self {
190        Self {
191            array: konst::array::from_fn!(|_| MaybeUninit::uninit()),
192            len:   0,
193        }
194    }
195
196    #[inline]
197    pub const fn len(&self) -> usize {
198        self.len
199    }
200
201    #[inline]
202    pub const fn is_empty(&self) -> bool {
203        self.len() == 0
204    }
205
206    #[inline]
207    pub const fn is_full(&self) -> bool {
208        self.len() == C
209    }
210
211    #[inline]
212    pub fn fill_rest(&mut self, item: &T)
213    where
214        T: Clone, {
215        for _ in self.len..C {
216            self.push(item.clone());
217        }
218    }
219
220    #[inline]
221    pub fn fill_rest_with(&mut self, mut pred: impl FnMut() -> T)
222    where
223        T: Clone, {
224        for _ in self.len..C {
225            self.push(pred());
226        }
227    }
228
229    #[inline]
230    pub const fn as_slice(&self) -> &[T] {
231        // SAFETY: every item 0..self.len is initialized.
232        unsafe { konst::slice::slice_up_to(&self.array, self.len).assume_init_ref() }
233    }
234
235    #[inline]
236    pub const fn as_slice_mut(&mut self) -> &mut [T] {
237        // SAFETY: every item 0..self.len is initialized.
238        unsafe { konst::slice::slice_up_to_mut(&mut self.array, self.len).assume_init_mut() }
239    }
240
241    #[inline]
242    pub const fn from_array(array: [T; C]) -> Self {
243        let array = konst::array::map!(array, MaybeUninit::new);
244        Self { array, len: C }
245    }
246
247    #[inline]
248    pub const fn as_array(&self) -> Option<&[T; C]> {
249        if self.is_full() {
250            // SAFETY: The array is full (len == capacity); therefore, all the values are
251            // initialized and valid.
252            Some(unsafe { reinterpret_array_ref(&self.array) })
253        } else {
254            None
255        }
256    }
257
258    #[inline]
259    pub const fn as_array_mut(&mut self) -> Option<&mut [T; C]> {
260        if self.is_full() {
261            // SAFETY: The array is full (len == capacity); therefore, all the values are
262            // initialized and valid.
263            Some(unsafe { reinterpret_array_mut(&mut self.array) })
264        } else {
265            None
266        }
267    }
268
269    /// Copy all elements from `slice` into a new [`ArrayVec`].
270    ///
271    /// Returns [`None`] if `slice` is larger than the capacity.
272    #[inline]
273    pub fn from_slice(slice: &[T]) -> Option<Self>
274    where
275        T: Clone, {
276        if slice.len() > C {
277            return None;
278        }
279
280        let mut array = konst::maybe_uninit::UNINIT_ARRAY::<T, C>::V;
281        array[..slice.len()].write_clone_of_slice(slice);
282
283        Some(Self {
284            array,
285            len: slice.len(),
286        })
287    }
288
289    /// Create a new [`ArrayVec`] containing references to all the values in
290    /// this one.
291    #[inline]
292    pub const fn ref_vec(&self) -> ArrayVec<C, &T> {
293        let mut array = konst::maybe_uninit::UNINIT_ARRAY::<&T, C>::V;
294        konst::iter::for_each! { (i, elem) in konst::slice::iter(self.as_slice()),enumerate() =>
295        // pub const fn iter(&self) -> ArrayVecIter<C, &T> {
296
297        // }
298
299                array[i].write(elem);
300            }
301
302        ArrayVec {
303            array,
304            len: self.len,
305        }
306    }
307
308    /// Create a new [`ArrayVec`] containing mutable references to all the
309    /// values in this one.
310    #[inline]
311    pub const fn mut_vec(&mut self) -> ArrayVec<C, &mut T> {
312        let len = self.len;
313        let mut array = konst::maybe_uninit::UNINIT_ARRAY::<&mut T, C>::V;
314        konst::iter::for_each! { (i, elem) in konst::slice::iter_mut(self.as_slice_mut()),enumerate() =>
315            array[i].write(elem);
316        }
317        ArrayVec { array, len }
318    }
319
320    /// Remove an the final element from the the vector.
321    ///
322    /// `None` is returned when the vector is empty.
323    #[inline]
324    pub const fn pop(&mut self) -> Option<T> {
325        if self.len == 0 {
326            return None;
327        }
328
329        self.len = self.len.strict_sub(1);
330
331        // SAFETY:
332        // - `self.len > 0`; therefore `self.len - 1` is a valid index.
333        // - `0..self.len` is initialized
334        // - `self.len` is decremented to prevent any reads of the duplicated element.
335        let item = unsafe { self.array[self.len].assume_init_read() };
336        Some(item)
337    }
338
339    /// Add an item to the back of the vector.
340    ///
341    /// # Panics
342    ///
343    /// This function panics when:
344    ///
345    /// 1. The array is full.
346    #[inline]
347    pub const fn push(&mut self, item: T) {
348        assert!(
349            self.len < C,
350            "Tried to push to a vector without enough capacity."
351        );
352
353        // SAFETY:
354        // - `self.len < C`; therefore, `self.len` is a valid index.
355        // - `0..self.len` are valid elements; therefore, writing to `self.len` doesn't
356        //   overwrite any valid and non-dropped elements.
357        // - `self.len` is incremented afterwards to prevent double-invocations that
358        //   cause missed `Drop`s.
359        self.array[self.len].write(item);
360        self.len = self.len.strict_add(1);
361    }
362
363    /// Add an item to the back of the vector.
364    ///
365    /// # Returns
366    ///
367    /// This function returns the provided item as the error variant when:
368    ///
369    /// - `index` is out of bounds.
370    #[inline]
371    pub const fn try_push(&mut self, item: T) -> Result<(), T> {
372        if self.len >= C {
373            return Err(item);
374        }
375
376        self.push(item);
377        Ok(())
378    }
379
380    /// Insert `item` at `index` shifting all the elements on the right by one,
381    /// and extend the length to acommodate.
382    ///
383    /// # Panics
384    ///
385    /// This function panics when:
386    ///
387    /// - The array is at it's maximum length.
388    #[inline]
389    pub const fn insert(&mut self, item: T, index: usize) {
390        assert!(self.len < C, "Tried to insert to a full vector.");
391        assert!(index <= self.len, "Index out of bounds.");
392
393        // NOTE: it's okay to ignore the result of this because we checked above that
394        // there is at least one invalid (thus removable) element at the end
395        // (`self.len < C`).
396        let _ = slice_shift_right(
397            konst::slice::slice_from_mut(&mut self.array, index),
398            [MaybeUninit::new(item)],
399        );
400        self.len = self.len.strict_add(1);
401    }
402
403    /// Attempt to insert `item` at `index` shifting all the elements on the
404    /// right by one, and extend the length to acommodate.
405    ///
406    /// # Returns
407    ///
408    /// This function returns the provided item as the error variant when:
409    ///
410    /// - The array is full.
411    /// - `index` is out of bounds.
412    #[inline]
413    pub const fn try_insert(&mut self, item: T, index: usize) -> Result<(), T> {
414        if self.len >= C || index > self.len {
415            return Err(item);
416        }
417        self.insert(item, index);
418        Ok(())
419    }
420
421    #[inline]
422    pub fn truncate(&mut self, len: usize) {
423        if len >= self.len {
424            return;
425        }
426
427        // SAFETY: These elements can be dropped because everything from `0..self.len`
428        // is initialized. The dropped elements will not be accessed again because
429        // `self.len` is set to `len`
430        unsafe { self.array[len..self.len].assume_init_drop() };
431        self.len = len;
432    }
433
434    /// Resize so that `len` is equal to `new_len`.
435    ///
436    /// If `new_len` is greater than `len`, the vec is extended by the
437    /// difference with each additional slot filled with `value`. If `new_len`
438    /// is less than `len`, the vec is truncated.
439    ///
440    /// # Panics
441    ///
442    /// This function panics when:
443    ///
444    /// 1. `new_len > C`
445    #[inline]
446    pub fn resize(&mut self, new_len: usize, value: T)
447    where
448        T: Clone, {
449        assert!(new_len <= C, "Tried to resize beyond capacity.");
450
451        if new_len < self.len {
452            self.truncate(new_len);
453        } else if new_len > self.len {
454            write_filled(&mut self.array[self.len..new_len], value);
455            self.len = new_len;
456        }
457    }
458}
459#[cfg(test)]
460#[cfg_attr(coverage_nightly, coverage(off))]
461mod tests {
462    use super::*;
463    use proptest::prelude::*;
464
465    fn proptest_config() -> ProptestConfig {
466        ProptestConfig {
467            #[cfg(miri)]
468            failure_persistence: None,
469            #[cfg(miri)]
470            cases: 32,
471            ..ProptestConfig::default()
472        }
473    }
474
475    #[test]
476    #[expect(clippy::undocumented_unsafe_blocks)]
477    fn ptr_cast_array_eq() {
478        let x = &[0u8; 4];
479        let x_ptr: *const u8 = x.as_ptr();
480
481        let y_ptr: *const [u8; 4] = ptr_cast_array(x_ptr);
482        let y = unsafe { y_ptr.as_ref().unwrap() };
483        assert_eq!(x, y);
484    }
485
486    #[test]
487    fn test_ptr_cast_array_mut() {
488        let x = &mut [0u8; 4];
489        let y_ptr: *mut [u8; 4] = ptr_cast_array_mut(x.as_mut_ptr());
490
491        assert_eq!(x.as_mut_ptr() as usize, y_ptr as usize);
492    }
493
494    #[test]
495    #[expect(clippy::undocumented_unsafe_blocks)]
496    fn test_reinterpret_array_ref() {
497        let x = &[0i32];
498        let y: &[u32; 1] = unsafe { reinterpret_array_ref(x) };
499        assert_eq!(x[0] as u32, y[0]);
500    }
501
502    #[test]
503    #[should_panic]
504    #[expect(clippy::undocumented_unsafe_blocks)]
505    fn test_reinterpret_array_ref_unequal_sizes() {
506        let x = &[0i32];
507        let _y: &[u128; 1] = unsafe { reinterpret_array_ref(x) };
508    }
509
510    #[test]
511    #[expect(clippy::undocumented_unsafe_blocks)]
512    fn test_reinterpret_array_mut() {
513        let mut x = [0x1i32];
514        let y: &mut [u32; 1] = unsafe { reinterpret_array_mut(&mut x) };
515        assert_eq!(0x1, y[0]);
516    }
517
518    #[test]
519    #[should_panic]
520    #[expect(clippy::undocumented_unsafe_blocks)]
521    fn test_reinterpret_array_mut_unequal_sizes() {
522        let mut x = [0x1i32];
523        let _y: &mut [u8; 1] = unsafe { reinterpret_array_mut(&mut x) };
524    }
525
526    #[test]
527    fn test_write_filled_empty() {
528        let mut vec: ArrayVec<0, ()> = ArrayVec::default();
529        write_filled(&mut vec.array, ());
530        assert!(vec.is_empty());
531    }
532
533    #[test]
534    fn default() {
535        let vec: ArrayVec<4, ()> = ArrayVec::default();
536        assert!(vec.is_empty());
537    }
538
539    #[test]
540    fn drop_empy() {
541        let x: ArrayVec<0, ()> = ArrayVec::new();
542        core::mem::drop(x);
543    }
544
545    #[test]
546    fn drop_heap_types() {
547        let x = ArrayVec::from_array([Box::new(0)]);
548        core::mem::drop(x);
549        let x = ArrayVec::from_array([String::from("I ♥ cum")]);
550        core::mem::drop(x);
551        let x = ArrayVec::from_array([vec![String::from("I ♥ you")]]);
552        core::mem::drop(x);
553    }
554
555    #[test]
556    fn clone() {
557        let vec = ArrayVec::from_array([1, 2, 3, 4]);
558        let mut vec2 = vec.clone();
559        assert_eq!(vec.as_slice(), vec2.as_slice());
560
561        vec2[1] = 69;
562        assert_eq!(vec[1], 2);
563    }
564
565    #[test]
566    fn len() {
567        const EXPECTED: [u32; 4] = [67, 69, 420, 80085];
568        let vec = ArrayVec::from_array(EXPECTED);
569        assert_eq!(vec.len(), EXPECTED.len());
570    }
571
572    #[test]
573    fn is_empty() {
574        let vec: ArrayVec<4, u8> = ArrayVec::new();
575        assert!(vec.is_empty());
576    }
577
578    #[test]
579    fn is_full() {
580        let vec: ArrayVec<4, u8> = ArrayVec::from_array([0; 4]);
581        assert!(vec.is_full());
582    }
583
584    #[test]
585    fn from_array() {
586        const EXPECTED: [u32; 4] = [67, 69, 420, 80085];
587        let vec = ArrayVec::from_array(EXPECTED);
588        assert_eq!(vec.as_slice(), EXPECTED);
589    }
590
591    #[test]
592    fn deref() {
593        let vec: ArrayVec<4, u8> = ArrayVec::from_array([0; 4]);
594        assert_eq!(&*vec, [0; 4]);
595    }
596
597    #[test]
598    fn deref_mut() {
599        let mut vec: ArrayVec<4, u8> = ArrayVec::from_array([0; 4]);
600        assert_eq!(&*vec, [0; 4]);
601
602        for item in &mut *vec {
603            *item = 10;
604        }
605        assert_eq!(&*vec, [10; 4]);
606    }
607
608    #[test]
609    fn from_slice() {
610        const EXPECTED: [u32; 4] = [67, 69, 420, 80085];
611        let vec = ArrayVec::<4, _>::from_slice(&EXPECTED).unwrap();
612        assert_eq!(vec.as_slice(), EXPECTED);
613    }
614
615    #[test]
616    #[should_panic]
617    fn from_slice_too_large() {
618        const EXPECTED: [u32; 4] = [67, 69, 420, 80085];
619        let _ = ArrayVec::<1, _>::from_slice(&EXPECTED).unwrap();
620    }
621
622    #[test]
623    fn as_array() {
624        let vec: ArrayVec<4, u8> = ArrayVec::from_array([69; 4]);
625        assert_eq!(&*vec, vec.as_array().unwrap());
626    }
627
628    #[test]
629    fn as_array_mut() {
630        let mut vec: ArrayVec<4, u8> = ArrayVec::from_array([69; 4]);
631        vec.as_array_mut().unwrap()[2] = 3;
632        assert_eq!(&*vec, [69, 69, 3, 69]);
633    }
634
635    #[test]
636    fn as_array_not_full() {
637        let vec: ArrayVec<4, u8> = ArrayVec::new();
638        assert_eq!(vec.as_array(), None);
639    }
640
641    #[test]
642    fn as_array_mut_not_full() {
643        let mut vec: ArrayVec<4, u8> = ArrayVec::new();
644        assert_eq!(vec.as_array_mut(), None);
645    }
646
647    #[test]
648    fn push() {
649        let mut vec: ArrayVec<5, u8> = ArrayVec::new();
650        vec.push(230);
651        assert_eq!(vec.as_slice(), &[230]);
652        vec.push(69);
653        assert_eq!(vec.as_slice(), &[230, 69]);
654        vec.push(101);
655        assert_eq!(vec.as_slice(), &[230, 69, 101]);
656    }
657
658    #[test]
659    #[should_panic]
660    fn push_beyond_capacity() {
661        let mut vec: ArrayVec<0, u8> = ArrayVec::new();
662        vec.push(69);
663    }
664
665    #[test]
666    fn pop_removes_values() {
667        let mut vec = ArrayVec::from_array([2, 3, 4]);
668        assert_eq!(vec.pop(), Some(4));
669        assert_eq!(&*vec, &[2, 3]);
670
671        assert_eq!(vec.pop(), Some(3));
672        assert_eq!(&*vec, &[2]);
673
674        assert_eq!(vec.pop(), Some(2));
675        assert_eq!(&*vec, &[]);
676
677        assert_eq!(vec.pop(), None);
678        assert_eq!(&*vec, &[]);
679    }
680
681    #[test]
682    fn pop_heap_types() {
683        let mut vec = ArrayVec::from_array([String::from("hey"), String::from("boy")]);
684        assert_eq!(vec.pop(), Some(String::from("boy")));
685        core::mem::drop(vec);
686    }
687
688    #[test]
689    fn push_pop() {
690        let mut vec = ArrayVec::<2, u8>::new();
691
692        vec.push(1);
693        assert_eq!(vec.pop(), Some(1));
694        assert_eq!(&*vec, &[]);
695
696        vec.push(8);
697        assert_eq!(vec.pop(), Some(8));
698        assert_eq!(&*vec, &[]);
699    }
700
701    #[test]
702    fn try_push_ok() {
703        let mut vec: ArrayVec<2, u8> = ArrayVec::new();
704        assert_eq!(vec.try_push(1), Ok(()));
705        assert_eq!(vec.try_push(2), Ok(()));
706    }
707
708    #[test]
709    fn try_push_full() {
710        let mut vec: ArrayVec<1, u8> = ArrayVec::new();
711        vec.push(1);
712        assert_eq!(vec.try_push(99), Err(99));
713        assert_eq!(vec.as_slice(), &[1]);
714    }
715
716    #[test]
717    fn try_insert() {
718        let mut vec: ArrayVec<4, u8> = ArrayVec::from_slice(&[1, 3]).unwrap();
719        assert_eq!(vec.try_insert(2, 1), Ok(()));
720        assert_eq!(vec.as_slice(), &[1, 2, 3]);
721    }
722
723    #[test]
724    fn try_insert_out_of_bounds() {
725        let mut vec: ArrayVec<4, u8> = ArrayVec::new();
726        assert!(vec.try_insert(0, 1).is_err());
727    }
728
729    #[test]
730    fn truncate() {
731        let mut vec = ArrayVec::from_array([1, 2, 3, 4]);
732
733        vec.truncate(2);
734        assert_eq!(vec.as_slice(), [1, 2]);
735        vec.push(0);
736        assert_eq!(vec.as_slice(), [1, 2, 0]);
737        vec.truncate(0);
738        assert_eq!(vec.as_slice(), []);
739        vec.truncate(0xcafebabe);
740        assert!(vec.is_empty());
741    }
742
743    #[test]
744    fn truncate_heap_types() {
745        let mut vec = ArrayVec::from_array([String::from("hey"), String::from("boy")]);
746
747        vec.truncate(1);
748        assert_eq!(vec.as_slice(), [String::from("hey")]);
749        core::mem::drop(vec);
750    }
751
752    #[test]
753    fn truncate_noop() {
754        let mut vec = ArrayVec::from_array([1, 2, 3, 4]);
755
756        // Anything >= len is a no-op
757        vec.truncate(4);
758        assert_eq!(vec.len(), 4);
759        vec.truncate(10);
760        assert_eq!(vec.len(), 4);
761    }
762
763    #[test]
764    fn resize_truncate() {
765        let mut vec = ArrayVec::from_array([1, 2, 3, 4]);
766
767        vec.resize(2, 0);
768        assert_eq!(vec.len(), 2);
769    }
770
771    #[test]
772    #[should_panic]
773    fn resize_beyond_capacity() {
774        let mut vec = ArrayVec::<1, _>::from_slice(&[1]).unwrap();
775
776        vec.resize(2, 0);
777    }
778
779    #[test]
780    fn resize_extend_heap_types() {
781        let mut vec = ArrayVec::<1, _>::from_slice(&[]).unwrap();
782
783        vec.resize(1, String::from("girls rule"));
784        assert_eq!(vec.len(), 1);
785        assert_eq!(vec.as_slice(), [String::from("girls rule")]);
786    }
787
788    #[test]
789    fn insert() {
790        const EXPECTED: [u32; 4] = [67, 69, 420, 80085];
791        let vec: ArrayVec<4, u32> = {
792            let mut vec = ArrayVec::<4, _>::from_slice(&[67, 420, 80085]).unwrap();
793            vec.insert(69, 1);
794            vec
795        };
796        assert_eq!(vec.as_slice(), EXPECTED);
797    }
798
799    #[test]
800    #[should_panic]
801    fn insert_full() {
802        let mut vec = ArrayVec::<0, u64>::from_array([]);
803        vec.insert(0xcafebabe, 0);
804    }
805
806    proptest! {
807        #![proptest_config(proptest_config())]
808        #[test]
809        fn resize_extend(
810            initial in prop::collection::vec(0u8..=255, 0..4usize),
811            fill: u8,
812            extra in 0..5usize,
813        ) {
814            let new_len = initial.len() + extra;
815            let mut vec = ArrayVec::<8, u8>::from_slice(&initial).unwrap();
816            vec.resize(new_len, fill);
817
818            assert_eq!(&vec.as_slice()[..initial.len()], initial.as_slice());
819            assert!(vec.as_slice()[initial.len()..].iter().all(|&x| x == fill));
820            assert_eq!(vec.len(), new_len);
821        }
822    }
823
824    #[test]
825    fn ref_vec() {
826        let vec = ArrayVec::from_array([7; 4]);
827        let slice: ArrayVec<4, &i32> = vec.ref_vec();
828        assert!(vec.iter().zip(slice.iter().copied()).all(|(&l, r)| l.eq(r)));
829    }
830
831    #[test]
832    fn mut_vec() {
833        let mut vec = ArrayVec::from_array([7; 4]);
834        let slice: ArrayVec<4, &mut i32> = vec.mut_vec();
835
836        for x in slice {
837            *x = 69; // I'm so horny
838        }
839
840        assert_eq!(&*vec, [69; 4]);
841    }
842
843    #[test]
844    fn debug_noop() {
845        let vec = ArrayVec::from_array([1u8, 2, 3, 4]);
846        eprintln!("{vec:?}");
847    }
848
849    #[test]
850    fn partial_eq() {
851        let a = ArrayVec::from_array([1u8, 2, 3]);
852        let b = ArrayVec::from_array([1u8, 2, 3]);
853        let c = ArrayVec::from_array([1u8, 2, 4]);
854        assert_eq!(a, b);
855        assert_ne!(a, c);
856    }
857
858    #[test]
859    fn ord() {
860        let a = ArrayVec::from_array([1u8, 2, 3]);
861        let b = ArrayVec::from_array([1u8, 2, 4]);
862        assert!(a < b);
863    }
864
865    proptest! {
866        #![proptest_config(proptest_config())]
867        #[test]
868        fn shift_right_semantics(
869            original in prop::collection::vec(0u8..=255, 0..16),
870            item: u8,
871        ) {
872            // Build conceptual [item, original...], then split
873            let mut expected_slice = vec![item];
874            expected_slice.extend_from_slice(&original);
875            expected_slice.truncate(original.len()); // first `len` stay
876            let expected_returned = {
877                let mut full = vec![item];
878                full.extend_from_slice(&original);
879                full[original.len()..].to_vec()        // last 1 is returned
880            };
881
882            let mut buf = original.clone();
883            let returned = slice_shift_right(&mut buf, [item]);
884
885            assert_eq!(buf, expected_slice);
886            assert_eq!(returned, expected_returned.as_slice());
887        }
888    }
889
890    #[derive(Debug, Clone)]
891    enum Op {
892        Push(u8),
893        TryPush(u8),
894        Pop,
895        Insert(u8, usize),
896        TryInsert(u8, usize),
897        Truncate(usize),
898        Resize(usize, u8),
899    }
900
901    fn arbatrary_op() -> impl Strategy<Value = Op> {
902        prop_oneof![
903            any::<u8>().prop_map(Op::Push),
904            any::<u8>().prop_map(Op::TryPush),
905            Just(Op::Pop),
906            (any::<u8>(), any::<usize>()).prop_map(|(v, i)| Op::Insert(v, i)),
907            (any::<u8>(), any::<usize>()).prop_map(|(v, i)| Op::TryInsert(v, i)),
908            any::<usize>().prop_map(Op::Truncate),
909            (any::<u8>(), any::<usize>()).prop_map(|(v, i)| Op::Resize(i, v)),
910        ]
911    }
912
913    fn model_try_push(v: &mut Vec<u8>, value: u8) -> Result<(), u8> {
914        if v.len() >= v.capacity() {
915            return Err(value);
916        }
917
918        v.push(value);
919        Ok(())
920    }
921
922    fn model_try_insert(v: &mut Vec<u8>, value: u8, idx: usize) -> Result<(), u8> {
923        if v.len() >= v.capacity() || idx > v.len() {
924            return Err(value);
925        }
926
927        v.insert(idx, value);
928        Ok(())
929    }
930
931    proptest! {
932        #![proptest_config(proptest_config())]
933        #[test]
934        fn model_based(ops in prop::collection::vec(arbatrary_op(), 0..50)) {
935            const C: usize = 8;
936            let mut vec: ArrayVec<C, u8> = ArrayVec::new();
937            let mut model: Vec<u8> = Vec::with_capacity(C);
938
939            for op in ops {
940                match op {
941                    Op::Push(v) => {
942                        if model.len() < C {
943                            vec.push(v);
944                            model.push(v);
945                        }
946                    }
947                    Op::TryPush(x) => {
948                        assert_eq!(vec.try_push(x), model_try_push(&mut model, x));
949                    }
950                    Op::Pop => {
951                        assert_eq!(vec.pop(), model.pop());
952                    }
953                    Op::Insert(v, i) => {
954                        if model.len() < C {
955                            let idx = i % (model.len() + 1);
956                            vec.insert(v, idx);
957                            model.insert(idx, v);
958                        }
959                    }
960                    Op::TryInsert(val, idx) => {
961                        assert_eq!(
962                            vec.try_insert(val, idx),
963                            model_try_insert(&mut model, val, idx)
964                        );
965                    }
966                    Op::Truncate(n) => {
967                        let n = n % (C + 1);
968                        vec.truncate(n);
969                        model.truncate(n);
970                    }
971                    Op::Resize(n, x) => {
972                        let n = n % (C + 1);
973                        vec.resize(n, x);
974                        model.resize(n,x);
975                    }
976                }
977                assert_eq!(vec.as_slice(), model.as_slice());
978                assert!(vec.len() <= C);
979            }
980        }
981    }
982}