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