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 konst::for_range! { _ in self.len..C => {
216 self.push(item.clone());
217 }}
218 }
219
220 #[inline]
221 pub const fn as_slice(&self) -> &[T] {
222 unsafe { konst::slice::slice_up_to(&self.array, self.len).assume_init_ref() }
224 }
225
226 #[inline]
227 pub const fn as_slice_mut(&mut self) -> &mut [T] {
228 unsafe { konst::slice::slice_up_to_mut(&mut self.array, self.len).assume_init_mut() }
230 }
231
232 #[inline]
233 pub const fn from_array(array: [T; C]) -> Self {
234 let array = konst::array::map!(array, MaybeUninit::new);
235 Self { array, len: C }
236 }
237
238 #[inline]
239 pub const fn as_array(&self) -> Option<&[T; C]> {
240 if self.is_full() {
241 Some(unsafe { reinterpret_array_ref(&self.array) })
244 } else {
245 None
246 }
247 }
248
249 #[inline]
250 pub const fn as_array_mut(&mut self) -> Option<&mut [T; C]> {
251 if self.is_full() {
252 Some(unsafe { reinterpret_array_mut(&mut self.array) })
255 } else {
256 None
257 }
258 }
259
260 #[inline]
264 pub fn from_slice(slice: &[T]) -> Option<Self>
265 where
266 T: Clone, {
267 if slice.len() > C {
268 return None;
269 }
270
271 let mut array = konst::maybe_uninit::UNINIT_ARRAY::<T, C>::V;
272 array[..slice.len()].write_clone_of_slice(slice);
273
274 Some(Self {
275 array,
276 len: slice.len(),
277 })
278 }
279
280 #[inline]
283 pub const fn ref_vec(&self) -> ArrayVec<C, &T> {
284 let mut array = konst::maybe_uninit::UNINIT_ARRAY::<&T, C>::V;
285 konst::iter::for_each! { (i, elem) in konst::slice::iter(self.as_slice()),enumerate() =>
286 array[i].write(elem);
291 }
292
293 ArrayVec {
294 array,
295 len: self.len,
296 }
297 }
298
299 #[inline]
302 pub const fn mut_vec(&mut self) -> ArrayVec<C, &mut T> {
303 let len = self.len;
304 let mut array = konst::maybe_uninit::UNINIT_ARRAY::<&mut T, C>::V;
305 konst::iter::for_each! { (i, elem) in konst::slice::iter_mut(self.as_slice_mut()),enumerate() =>
306 array[i].write(elem);
307 }
308 ArrayVec { array, len }
309 }
310
311 #[inline]
315 pub const fn pop(&mut self) -> Option<T> {
316 if self.len == 0 {
317 return None;
318 }
319
320 self.len = self.len.strict_sub(1);
321
322 let item = unsafe { self.array[self.len].assume_init_read() };
327 Some(item)
328 }
329
330 #[inline]
338 pub const fn push(&mut self, item: T) {
339 assert!(
340 self.len < C,
341 "Tried to push to a vector without enough capacity."
342 );
343
344 self.array[self.len].write(item);
351 self.len = self.len.strict_add(1);
352 }
353
354 #[inline]
362 pub const fn try_push(&mut self, item: T) -> Result<(), T> {
363 if self.len >= C {
364 return Err(item);
365 }
366
367 self.push(item);
368 Ok(())
369 }
370
371 #[inline]
380 pub const fn insert(&mut self, item: T, index: usize) {
381 assert!(self.len < C, "Tried to insert to a full vector.");
382 assert!(index <= self.len, "Index out of bounds.");
383
384 let _ = slice_shift_right(
388 konst::slice::slice_from_mut(&mut self.array, index),
389 [MaybeUninit::new(item)],
390 );
391 self.len = self.len.strict_add(1);
392 }
393
394 #[inline]
404 pub const fn try_insert(&mut self, item: T, index: usize) -> Result<(), T> {
405 if self.len >= C || index > self.len {
406 return Err(item);
407 }
408 self.insert(item, index);
409 Ok(())
410 }
411
412 #[inline]
413 pub fn truncate(&mut self, len: usize) {
414 if len >= self.len {
415 return;
416 }
417
418 unsafe { self.array[len..self.len].assume_init_drop() };
422 self.len = len;
423 }
424
425 #[inline]
437 pub fn resize(&mut self, new_len: usize, value: T)
438 where
439 T: Clone, {
440 assert!(new_len <= C, "Tried to resize beyond capacity.");
441
442 if new_len < self.len {
443 self.truncate(new_len);
444 } else if new_len > self.len {
445 write_filled(&mut self.array[self.len..new_len], value);
446 self.len = new_len;
447 }
448 }
449}
450#[cfg(test)]
451#[cfg_attr(coverage_nightly, coverage(off))]
452mod tests {
453 use super::*;
454 use proptest::prelude::*;
455
456 fn proptest_config() -> ProptestConfig {
457 ProptestConfig {
458 #[cfg(miri)]
459 failure_persistence: None,
460 #[cfg(miri)]
461 cases: 32,
462 ..ProptestConfig::default()
463 }
464 }
465
466 #[test]
467 #[expect(clippy::undocumented_unsafe_blocks)]
468 fn ptr_cast_array_eq() {
469 let x = &[0u8; 4];
470 let x_ptr: *const u8 = x.as_ptr();
471
472 let y_ptr: *const [u8; 4] = ptr_cast_array(x_ptr);
473 let y = unsafe { y_ptr.as_ref().unwrap() };
474 assert_eq!(x, y);
475 }
476
477 #[test]
478 fn test_ptr_cast_array_mut() {
479 let x = &mut [0u8; 4];
480 let y_ptr: *mut [u8; 4] = ptr_cast_array_mut(x.as_mut_ptr());
481
482 assert_eq!(x.as_mut_ptr() as usize, y_ptr as usize);
483 }
484
485 #[test]
486 #[expect(clippy::undocumented_unsafe_blocks)]
487 fn test_reinterpret_array_ref() {
488 let x = &[0i32];
489 let y: &[u32; 1] = unsafe { reinterpret_array_ref(x) };
490 assert_eq!(x[0] as u32, y[0]);
491 }
492
493 #[test]
494 #[should_panic]
495 #[expect(clippy::undocumented_unsafe_blocks)]
496 fn test_reinterpret_array_ref_unequal_sizes() {
497 let x = &[0i32];
498 let _y: &[u128; 1] = unsafe { reinterpret_array_ref(x) };
499 }
500
501 #[test]
502 #[expect(clippy::undocumented_unsafe_blocks)]
503 fn test_reinterpret_array_mut() {
504 let mut x = [0x1i32];
505 let y: &mut [u32; 1] = unsafe { reinterpret_array_mut(&mut x) };
506 assert_eq!(0x1, y[0]);
507 }
508
509 #[test]
510 #[should_panic]
511 #[expect(clippy::undocumented_unsafe_blocks)]
512 fn test_reinterpret_array_mut_unequal_sizes() {
513 let mut x = [0x1i32];
514 let _y: &mut [u8; 1] = unsafe { reinterpret_array_mut(&mut x) };
515 }
516
517 #[test]
518 fn test_write_filled_empty() {
519 let mut vec: ArrayVec<0, ()> = ArrayVec::default();
520 write_filled(&mut vec.array, ());
521 assert!(vec.is_empty());
522 }
523
524 #[test]
525 fn default() {
526 let vec: ArrayVec<4, ()> = ArrayVec::default();
527 assert!(vec.is_empty());
528 }
529
530 #[test]
531 fn drop_empy() {
532 let x: ArrayVec<0, ()> = ArrayVec::new();
533 core::mem::drop(x);
534 }
535
536 #[test]
537 fn drop_heap_types() {
538 let x = ArrayVec::from_array([Box::new(0)]);
539 core::mem::drop(x);
540 let x = ArrayVec::from_array([String::from("I ♥ cum")]);
541 core::mem::drop(x);
542 let x = ArrayVec::from_array([vec![String::from("I ♥ you")]]);
543 core::mem::drop(x);
544 }
545
546 #[test]
547 fn clone() {
548 let vec = ArrayVec::from_array([1, 2, 3, 4]);
549 let mut vec2 = vec.clone();
550 assert_eq!(vec.as_slice(), vec2.as_slice());
551
552 vec2[1] = 69;
553 assert_eq!(vec[1], 2);
554 }
555
556 #[test]
557 fn len() {
558 const EXPECTED: [u32; 4] = [67, 69, 420, 80085];
559 let vec = ArrayVec::from_array(EXPECTED);
560 assert_eq!(vec.len(), EXPECTED.len());
561 }
562
563 #[test]
564 fn is_empty() {
565 let vec: ArrayVec<4, u8> = ArrayVec::new();
566 assert!(vec.is_empty());
567 }
568
569 #[test]
570 fn is_full() {
571 let vec: ArrayVec<4, u8> = ArrayVec::from_array([0; 4]);
572 assert!(vec.is_full());
573 }
574
575 #[test]
576 fn from_array() {
577 const EXPECTED: [u32; 4] = [67, 69, 420, 80085];
578 let vec = ArrayVec::from_array(EXPECTED);
579 assert_eq!(vec.as_slice(), EXPECTED);
580 }
581
582 #[test]
583 fn deref() {
584 let vec: ArrayVec<4, u8> = ArrayVec::from_array([0; 4]);
585 assert_eq!(&*vec, [0; 4]);
586 }
587
588 #[test]
589 fn deref_mut() {
590 let mut vec: ArrayVec<4, u8> = ArrayVec::from_array([0; 4]);
591 assert_eq!(&*vec, [0; 4]);
592
593 for item in &mut *vec {
594 *item = 10;
595 }
596 assert_eq!(&*vec, [10; 4]);
597 }
598
599 #[test]
600 fn from_slice() {
601 const EXPECTED: [u32; 4] = [67, 69, 420, 80085];
602 let vec = ArrayVec::<4, _>::from_slice(&EXPECTED).unwrap();
603 assert_eq!(vec.as_slice(), EXPECTED);
604 }
605
606 #[test]
607 #[should_panic]
608 fn from_slice_too_large() {
609 const EXPECTED: [u32; 4] = [67, 69, 420, 80085];
610 let _ = ArrayVec::<1, _>::from_slice(&EXPECTED).unwrap();
611 }
612
613 #[test]
614 fn as_array() {
615 let vec: ArrayVec<4, u8> = ArrayVec::from_array([69; 4]);
616 assert_eq!(&*vec, vec.as_array().unwrap());
617 }
618
619 #[test]
620 fn as_array_mut() {
621 let mut vec: ArrayVec<4, u8> = ArrayVec::from_array([69; 4]);
622 vec.as_array_mut().unwrap()[2] = 3;
623 assert_eq!(&*vec, [69, 69, 3, 69]);
624 }
625
626 #[test]
627 fn as_array_not_full() {
628 let vec: ArrayVec<4, u8> = ArrayVec::new();
629 assert_eq!(vec.as_array(), None);
630 }
631
632 #[test]
633 fn as_array_mut_not_full() {
634 let mut vec: ArrayVec<4, u8> = ArrayVec::new();
635 assert_eq!(vec.as_array_mut(), None);
636 }
637
638 #[test]
639 fn push() {
640 let mut vec: ArrayVec<5, u8> = ArrayVec::new();
641 vec.push(230);
642 assert_eq!(vec.as_slice(), &[230]);
643 vec.push(69);
644 assert_eq!(vec.as_slice(), &[230, 69]);
645 vec.push(101);
646 assert_eq!(vec.as_slice(), &[230, 69, 101]);
647 }
648
649 #[test]
650 #[should_panic]
651 fn push_beyond_capacity() {
652 let mut vec: ArrayVec<0, u8> = ArrayVec::new();
653 vec.push(69);
654 }
655
656 #[test]
657 fn pop_removes_values() {
658 let mut vec = ArrayVec::from_array([2, 3, 4]);
659 assert_eq!(vec.pop(), Some(4));
660 assert_eq!(&*vec, &[2, 3]);
661
662 assert_eq!(vec.pop(), Some(3));
663 assert_eq!(&*vec, &[2]);
664
665 assert_eq!(vec.pop(), Some(2));
666 assert_eq!(&*vec, &[]);
667
668 assert_eq!(vec.pop(), None);
669 assert_eq!(&*vec, &[]);
670 }
671
672 #[test]
673 fn pop_heap_types() {
674 let mut vec = ArrayVec::from_array([String::from("hey"), String::from("boy")]);
675 assert_eq!(vec.pop(), Some(String::from("boy")));
676 core::mem::drop(vec);
677 }
678
679 #[test]
680 fn push_pop() {
681 let mut vec = ArrayVec::<2, u8>::new();
682
683 vec.push(1);
684 assert_eq!(vec.pop(), Some(1));
685 assert_eq!(&*vec, &[]);
686
687 vec.push(8);
688 assert_eq!(vec.pop(), Some(8));
689 assert_eq!(&*vec, &[]);
690 }
691
692 #[test]
693 fn try_push_ok() {
694 let mut vec: ArrayVec<2, u8> = ArrayVec::new();
695 assert_eq!(vec.try_push(1), Ok(()));
696 assert_eq!(vec.try_push(2), Ok(()));
697 }
698
699 #[test]
700 fn try_push_full() {
701 let mut vec: ArrayVec<1, u8> = ArrayVec::new();
702 vec.push(1);
703 assert_eq!(vec.try_push(99), Err(99));
704 assert_eq!(vec.as_slice(), &[1]);
705 }
706
707 #[test]
708 fn try_insert() {
709 let mut vec: ArrayVec<4, u8> = ArrayVec::from_slice(&[1, 3]).unwrap();
710 assert_eq!(vec.try_insert(2, 1), Ok(()));
711 assert_eq!(vec.as_slice(), &[1, 2, 3]);
712 }
713
714 #[test]
715 fn try_insert_out_of_bounds() {
716 let mut vec: ArrayVec<4, u8> = ArrayVec::new();
717 assert!(vec.try_insert(0, 1).is_err());
718 }
719
720 #[test]
721 fn truncate() {
722 let mut vec = ArrayVec::from_array([1, 2, 3, 4]);
723
724 vec.truncate(2);
725 assert_eq!(vec.as_slice(), [1, 2]);
726 vec.push(0);
727 assert_eq!(vec.as_slice(), [1, 2, 0]);
728 vec.truncate(0);
729 assert_eq!(vec.as_slice(), []);
730 vec.truncate(0xcafebabe);
731 assert!(vec.is_empty());
732 }
733
734 #[test]
735 fn truncate_heap_types() {
736 let mut vec = ArrayVec::from_array([String::from("hey"), String::from("boy")]);
737
738 vec.truncate(1);
739 assert_eq!(vec.as_slice(), [String::from("hey")]);
740 core::mem::drop(vec);
741 }
742
743 #[test]
744 fn truncate_noop() {
745 let mut vec = ArrayVec::from_array([1, 2, 3, 4]);
746
747 vec.truncate(4);
749 assert_eq!(vec.len(), 4);
750 vec.truncate(10);
751 assert_eq!(vec.len(), 4);
752 }
753
754 #[test]
755 fn resize_truncate() {
756 let mut vec = ArrayVec::from_array([1, 2, 3, 4]);
757
758 vec.resize(2, 0);
759 assert_eq!(vec.len(), 2);
760 }
761
762 #[test]
763 #[should_panic]
764 fn resize_beyond_capacity() {
765 let mut vec = ArrayVec::<1, _>::from_slice(&[1]).unwrap();
766
767 vec.resize(2, 0);
768 }
769
770 #[test]
771 fn resize_extend_heap_types() {
772 let mut vec = ArrayVec::<1, _>::from_slice(&[]).unwrap();
773
774 vec.resize(1, String::from("girls rule"));
775 assert_eq!(vec.len(), 1);
776 assert_eq!(vec.as_slice(), [String::from("girls rule")]);
777 }
778
779 #[test]
780 fn insert() {
781 const EXPECTED: [u32; 4] = [67, 69, 420, 80085];
782 let vec: ArrayVec<4, u32> = {
783 let mut vec = ArrayVec::<4, _>::from_slice(&[67, 420, 80085]).unwrap();
784 vec.insert(69, 1);
785 vec
786 };
787 assert_eq!(vec.as_slice(), EXPECTED);
788 }
789
790 #[test]
791 #[should_panic]
792 fn insert_full() {
793 let mut vec = ArrayVec::<0, u64>::from_array([]);
794 vec.insert(0xcafebabe, 0);
795 }
796
797 proptest! {
798 #![proptest_config(proptest_config())]
799 #[test]
800 fn resize_extend(
801 initial in prop::collection::vec(0u8..=255, 0..4usize),
802 fill: u8,
803 extra in 0..5usize,
804 ) {
805 let new_len = initial.len() + extra;
806 let mut vec = ArrayVec::<8, u8>::from_slice(&initial).unwrap();
807 vec.resize(new_len, fill);
808
809 assert_eq!(&vec.as_slice()[..initial.len()], initial.as_slice());
810 assert!(vec.as_slice()[initial.len()..].iter().all(|&x| x == fill));
811 assert_eq!(vec.len(), new_len);
812 }
813 }
814
815 #[test]
816 fn ref_vec() {
817 let vec = ArrayVec::from_array([7; 4]);
818 let slice: ArrayVec<4, &i32> = vec.ref_vec();
819 assert!(vec.iter().zip(slice.iter().copied()).all(|(&l, r)| l.eq(r)));
820 }
821
822 #[test]
823 fn mut_vec() {
824 let mut vec = ArrayVec::from_array([7; 4]);
825 let slice: ArrayVec<4, &mut i32> = vec.mut_vec();
826
827 for x in slice {
828 *x = 69; }
830
831 assert_eq!(&*vec, [69; 4]);
832 }
833
834 #[test]
835 fn debug_noop() {
836 let vec = ArrayVec::from_array([1u8, 2, 3, 4]);
837 eprintln!("{vec:?}");
838 }
839
840 #[test]
841 fn partial_eq() {
842 let a = ArrayVec::from_array([1u8, 2, 3]);
843 let b = ArrayVec::from_array([1u8, 2, 3]);
844 let c = ArrayVec::from_array([1u8, 2, 4]);
845 assert_eq!(a, b);
846 assert_ne!(a, c);
847 }
848
849 #[test]
850 fn ord() {
851 let a = ArrayVec::from_array([1u8, 2, 3]);
852 let b = ArrayVec::from_array([1u8, 2, 4]);
853 assert!(a < b);
854 }
855
856 proptest! {
857 #![proptest_config(proptest_config())]
858 #[test]
859 fn shift_right_semantics(
860 original in prop::collection::vec(0u8..=255, 0..16),
861 item: u8,
862 ) {
863 let mut expected_slice = vec![item];
865 expected_slice.extend_from_slice(&original);
866 expected_slice.truncate(original.len()); let expected_returned = {
868 let mut full = vec![item];
869 full.extend_from_slice(&original);
870 full[original.len()..].to_vec() };
872
873 let mut buf = original.clone();
874 let returned = slice_shift_right(&mut buf, [item]);
875
876 assert_eq!(buf, expected_slice);
877 assert_eq!(returned, expected_returned.as_slice());
878 }
879 }
880
881 #[derive(Debug, Clone)]
882 enum Op {
883 Push(u8),
884 TryPush(u8),
885 Pop,
886 Insert(u8, usize),
887 TryInsert(u8, usize),
888 Truncate(usize),
889 Resize(usize, u8),
890 }
891
892 fn arbatrary_op() -> impl Strategy<Value = Op> {
893 prop_oneof![
894 any::<u8>().prop_map(Op::Push),
895 any::<u8>().prop_map(Op::TryPush),
896 Just(Op::Pop),
897 (any::<u8>(), any::<usize>()).prop_map(|(v, i)| Op::Insert(v, i)),
898 (any::<u8>(), any::<usize>()).prop_map(|(v, i)| Op::TryInsert(v, i)),
899 any::<usize>().prop_map(Op::Truncate),
900 (any::<u8>(), any::<usize>()).prop_map(|(v, i)| Op::Resize(i, v)),
901 ]
902 }
903
904 fn model_try_push(v: &mut Vec<u8>, value: u8) -> Result<(), u8> {
905 if v.len() >= v.capacity() {
906 return Err(value);
907 }
908
909 v.push(value);
910 Ok(())
911 }
912
913 fn model_try_insert(v: &mut Vec<u8>, value: u8, idx: usize) -> Result<(), u8> {
914 if v.len() >= v.capacity() || idx > v.len() {
915 return Err(value);
916 }
917
918 v.insert(idx, value);
919 Ok(())
920 }
921
922 proptest! {
923 #![proptest_config(proptest_config())]
924 #[test]
925 fn model_based(ops in prop::collection::vec(arbatrary_op(), 0..50)) {
926 const C: usize = 8;
927 let mut vec: ArrayVec<C, u8> = ArrayVec::new();
928 let mut model: Vec<u8> = Vec::with_capacity(C);
929
930 for op in ops {
931 match op {
932 Op::Push(v) => {
933 if model.len() < C {
934 vec.push(v);
935 model.push(v);
936 }
937 }
938 Op::TryPush(x) => {
939 assert_eq!(vec.try_push(x), model_try_push(&mut model, x));
940 }
941 Op::Pop => {
942 assert_eq!(vec.pop(), model.pop());
943 }
944 Op::Insert(v, i) => {
945 if model.len() < C {
946 let idx = i % (model.len() + 1);
947 vec.insert(v, idx);
948 model.insert(idx, v);
949 }
950 }
951 Op::TryInsert(val, idx) => {
952 assert_eq!(
953 vec.try_insert(val, idx),
954 model_try_insert(&mut model, val, idx)
955 );
956 }
957 Op::Truncate(n) => {
958 let n = n % (C + 1);
959 vec.truncate(n);
960 model.truncate(n);
961 }
962 Op::Resize(n, x) => {
963 let n = n % (C + 1);
964 vec.resize(n, x);
965 model.resize(n,x);
966 }
967 }
968 assert_eq!(vec.as_slice(), model.as_slice());
969 assert!(vec.len() <= C);
970 }
971 }
972 }
973}