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
53const 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 unsafe { dest_array_ptr.as_ref_unchecked() }
71}
72
73const 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 unsafe { dest_array_ptr.as_mut_unchecked() }
93}
94
95const 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 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 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
150impl<const C: usize, T> Drop for ArrayVec<C, T> {
155 #[inline]
156 fn drop(&mut self) {
157 for i in 0..self.len {
158 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 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 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 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 Some(unsafe { reinterpret_array_mut(&mut self.array) })
264 } else {
265 None
266 }
267 }
268
269 #[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 #[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 array[i].write(elem);
300 }
301
302 ArrayVec {
303 array,
304 len: self.len,
305 }
306 }
307
308 #[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 #[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 let item = unsafe { self.array[self.len].assume_init_read() };
336 Some(item)
337 }
338
339 #[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 self.array[self.len].write(item);
360 self.len = self.len.strict_add(1);
361 }
362
363 #[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 #[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 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 #[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 unsafe { self.array[len..self.len].assume_init_drop() };
431 self.len = len;
432 }
433
434 #[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 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; }
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 let mut expected_slice = vec![item];
874 expected_slice.extend_from_slice(&original);
875 expected_slice.truncate(original.len()); let expected_returned = {
877 let mut full = vec![item];
878 full.extend_from_slice(&original);
879 full[original.len()..].to_vec() };
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}