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")]
25mod nightly;
26
27#[cfg(not(feature = "nightly"))]
28mod stable;
29
30fn write_filled<T: Clone>(slice: &mut [MaybeUninit<T>], value: T) {
31 if slice.is_empty() {
32 return;
33 }
34
35 let len = slice.len();
36 for elem in &mut slice[..len.saturating_sub(1)] {
37 elem.write(value.clone());
38 }
39 slice[len.saturating_sub(1)].write(value);
40}
41
42const fn ptr_cast_array<const N: usize, T>(ptr: *const T) -> *const [T; N] {
43 ptr.cast()
44}
45
46const fn ptr_cast_array_mut<const N: usize, T>(ptr: *mut T) -> *mut [T; N] {
47 ptr.cast()
48}
49
50const unsafe fn reinterpret_array_ref<const N: usize, Src, Dest>(src: &[Src; N]) -> &[Dest; N] {
55 #[expect(clippy::manual_assert)]
56 if size_of::<Src>() != size_of::<Dest>() {
57 panic!("Src and Dest have different sizes");
58 }
59
60 let src_ptr: *const Src = src.as_ptr();
61 let dest_ptr: *const Dest = src_ptr.cast();
62 let dest_array_ptr: *const [Dest; N] = ptr_cast_array(dest_ptr);
63
64 unsafe { dest_array_ptr.as_ref_unchecked() }
68}
69
70const unsafe fn reinterpret_array_mut<const N: usize, Src, Dest>(
75 src: &mut [Src; N],
76) -> &mut [Dest; N] {
77 #[expect(clippy::manual_assert)]
78 if size_of::<Src>() != size_of::<Dest>() {
79 panic!("Src and Dest have different sizes");
80 }
81
82 let src_ptr: *mut Src = src.as_mut_ptr();
83 let dest_ptr: *mut Dest = src_ptr.cast();
84 let dest_array_ptr: *mut [Dest; N] = ptr_cast_array_mut(dest_ptr);
85
86 unsafe { dest_array_ptr.as_mut_unchecked() }
90}
91
92const fn slice_shift_right<const N: usize, T>(slice: &mut [T], inserted: [T; N]) -> [T; N] {
94 if let Some(shift) = slice.len().checked_sub(N) {
95 unsafe {
105 let ptr = slice.as_mut_ptr();
106 let returned = ptr_cast_array_mut::<N, _>(ptr.add(shift)).read();
107 ptr.add(N).copy_from(ptr, shift);
108 ptr_cast_array_mut::<N, _>(ptr).write(inserted);
109 returned
110 }
111 } else {
112 unsafe {
125 let len = slice.len();
126 let slice = slice.as_mut_ptr();
127 let inserted = mem::ManuallyDrop::new(inserted);
128 let inserted = (&raw const inserted).cast::<T>();
129
130 let mut returned = MaybeUninit::<[T; N]>::uninit();
131 let ptr = returned.as_mut_ptr().cast::<T>();
132 ptr.add(N.wrapping_sub(len))
133 .copy_from_nonoverlapping(slice, len);
134 ptr.copy_from_nonoverlapping(inserted.add(len), N.wrapping_sub(len));
135 slice.copy_from_nonoverlapping(inserted, len);
136 returned.assume_init()
137 }
138 }
139}
140
141#[must_use]
142pub struct ArrayVec<const C: usize, T> {
143 array: [MaybeUninit<T>; C],
144 len: usize,
145}
146
147impl<const C: usize, T> Drop for ArrayVec<C, T> {
152 #[inline]
153 fn drop(&mut self) {
154 for i in 0..self.len {
155 unsafe { self.array[i].assume_init_drop() };
158 }
159 }
160}
161
162impl<const C: usize, T: Clone> Clone for ArrayVec<C, T> {
163 #[inline]
164 fn clone(&self) -> Self {
165 let mut array = konst::maybe_uninit::UNINIT_ARRAY::<T, C>::V;
166 array[..self.len()].write_clone_of_slice(self.as_slice());
167
168 Self {
169 array,
170 len: self.len,
171 }
172 }
173}
174
175impl<const C: usize, T: core::fmt::Debug> core::fmt::Debug for ArrayVec<C, T> {
176 #[inline]
177 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
178 f.debug_list().entries(self.ref_vec().as_slice()).finish()
179 }
180}
181
182impl<const C: usize, T> ArrayVec<C, T> {
183 pub const CAPACITY: usize = C;
184
185 #[inline]
186 pub const fn new() -> Self {
187 Self {
188 array: konst::array::from_fn!(|_| MaybeUninit::uninit()),
189 len: 0,
190 }
191 }
192
193 #[inline]
194 pub const fn len(&self) -> usize {
195 self.len
196 }
197
198 #[inline]
199 pub const fn is_empty(&self) -> bool {
200 self.len() == 0
201 }
202
203 #[inline]
204 pub const fn is_full(&self) -> bool {
205 self.len() == C
206 }
207
208 #[inline]
209 pub const fn as_slice(&self) -> &[T] {
210 unsafe { konst::slice::slice_up_to(&self.array, self.len).assume_init_ref() }
212 }
213
214 #[inline]
215 pub const fn as_slice_mut(&mut self) -> &mut [T] {
216 unsafe { konst::slice::slice_up_to_mut(&mut self.array, self.len).assume_init_mut() }
218 }
219
220 #[inline]
221 pub const fn from_array(array: [T; C]) -> Self {
222 let array = konst::array::map!(array, MaybeUninit::new);
223 Self { array, len: C }
224 }
225
226 #[inline]
227 pub const fn as_array(&self) -> Option<&[T; C]> {
228 if self.is_full() {
229 Some(unsafe { reinterpret_array_ref(&self.array) })
232 } else {
233 None
234 }
235 }
236
237 #[inline]
238 pub const fn as_array_mut(&mut self) -> Option<&mut [T; C]> {
239 if self.is_full() {
240 Some(unsafe { reinterpret_array_mut(&mut self.array) })
243 } else {
244 None
245 }
246 }
247
248 #[inline]
252 pub fn from_slice(slice: &[T]) -> Option<Self>
253 where
254 T: Clone, {
255 if slice.len() > C {
256 return None;
257 }
258
259 let mut array = konst::maybe_uninit::UNINIT_ARRAY::<T, C>::V;
260 array[..slice.len()].write_clone_of_slice(slice);
261
262 Some(Self {
263 array,
264 len: slice.len(),
265 })
266 }
267
268 #[inline]
271 pub const fn ref_vec(&self) -> ArrayVec<C, &T> {
272 let mut array = konst::maybe_uninit::UNINIT_ARRAY::<&T, C>::V;
273 konst::iter::for_each! { (i, elem) in konst::slice::iter(self.as_slice()),enumerate() =>
274 array[i].write(elem);
279 }
280
281 ArrayVec {
282 array,
283 len: self.len,
284 }
285 }
286
287 #[inline]
290 pub const fn mut_vec(&mut self) -> ArrayVec<C, &mut T> {
291 let len = self.len;
292 let mut array = konst::maybe_uninit::UNINIT_ARRAY::<&mut T, C>::V;
293 konst::iter::for_each! { (i, elem) in konst::slice::iter_mut(self.as_slice_mut()),enumerate() =>
294 array[i].write(elem);
295 }
296 ArrayVec { array, len }
297 }
298
299 #[inline]
303 pub const fn pop(&mut self) -> Option<T> {
304 if self.len == 0 {
305 return None;
306 }
307
308 self.len = self.len.strict_sub(1);
309
310 let item = unsafe { self.array[self.len].assume_init_read() };
315 Some(item)
316 }
317
318 #[inline]
326 pub const fn push(&mut self, item: T) {
327 assert!(
328 self.len < C,
329 "Tried to push to a vector without enough capacity."
330 );
331
332 self.array[self.len].write(item);
339 self.len = self.len.strict_add(1);
340 }
341
342 #[inline]
350 pub const fn try_push(&mut self, item: T) -> Result<(), T> {
351 if self.len >= C {
352 return Err(item);
353 }
354
355 self.push(item);
356 Ok(())
357 }
358
359 #[inline]
368 pub const fn insert(&mut self, item: T, index: usize) {
369 assert!(self.len < C, "Tried to insert to a full vector.");
370 assert!(index <= self.len, "Index out of bounds.");
371
372 let _ = slice_shift_right(
376 konst::slice::slice_from_mut(&mut self.array, index),
377 [MaybeUninit::new(item)],
378 );
379 self.len = self.len.strict_add(1);
380 }
381
382 #[inline]
392 pub const fn try_insert(&mut self, item: T, index: usize) -> Result<(), T> {
393 if self.len >= C || index > self.len {
394 return Err(item);
395 }
396 self.insert(item, index);
397 Ok(())
398 }
399
400 #[inline]
401 pub fn truncate(&mut self, len: usize) {
402 if len >= self.len {
403 return;
404 }
405
406 unsafe { self.array[len..self.len].assume_init_drop() };
410 self.len = len;
411 }
412
413 #[inline]
425 pub fn resize(&mut self, new_len: usize, value: T)
426 where
427 T: Clone, {
428 assert!(new_len <= C, "Tried to resize beyond capacity.");
429
430 if new_len < self.len {
431 self.truncate(new_len);
432 } else if new_len > self.len {
433 write_filled(&mut self.array[self.len..new_len], value);
434 self.len = new_len;
435 }
436 }
437}
438#[cfg(test)]
439#[cfg_attr(coverage_nightly, coverage(off))]
440mod tests {
441 use super::*;
442 use proptest::prelude::*;
443
444 fn proptest_config() -> ProptestConfig {
445 ProptestConfig {
446 #[cfg(miri)]
447 failure_persistence: None,
448 #[cfg(miri)]
449 cases: 32,
450 ..ProptestConfig::default()
451 }
452 }
453
454 #[test]
455 #[expect(clippy::undocumented_unsafe_blocks)]
456 fn ptr_cast_array_eq() {
457 let x = &[0u8; 4];
458 let x_ptr: *const u8 = x.as_ptr();
459
460 let y_ptr: *const [u8; 4] = ptr_cast_array(x_ptr);
461 let y = unsafe { y_ptr.as_ref().unwrap() };
462 assert_eq!(x, y);
463 }
464
465 #[test]
466 fn test_ptr_cast_array_mut() {
467 let x = &mut [0u8; 4];
468 let y_ptr: *mut [u8; 4] = ptr_cast_array_mut(x.as_mut_ptr());
469
470 assert_eq!(x.as_mut_ptr() as usize, y_ptr as usize);
471 }
472
473 #[test]
474 #[expect(clippy::undocumented_unsafe_blocks)]
475 fn test_reinterpret_array_ref() {
476 let x = &[0i32];
477 let y: &[u32; 1] = unsafe { reinterpret_array_ref(x) };
478 assert_eq!(x[0] as u32, y[0]);
479 }
480
481 #[test]
482 #[should_panic]
483 #[expect(clippy::undocumented_unsafe_blocks)]
484 fn test_reinterpret_array_ref_unequal_sizes() {
485 let x = &[0i32];
486 let _y: &[u128; 1] = unsafe { reinterpret_array_ref(x) };
487 }
488
489 #[test]
490 #[expect(clippy::undocumented_unsafe_blocks)]
491 fn test_reinterpret_array_mut() {
492 let mut x = [0x1i32];
493 let y: &mut [u32; 1] = unsafe { reinterpret_array_mut(&mut x) };
494 assert_eq!(0x1, y[0]);
495 }
496
497 #[test]
498 #[should_panic]
499 #[expect(clippy::undocumented_unsafe_blocks)]
500 fn test_reinterpret_array_mut_unequal_sizes() {
501 let mut x = [0x1i32];
502 let _y: &mut [u8; 1] = unsafe { reinterpret_array_mut(&mut x) };
503 }
504
505 #[test]
506 fn test_write_filled_empty() {
507 let mut vec: ArrayVec<0, ()> = ArrayVec::default();
508 write_filled(&mut vec.array, ());
509 assert!(vec.is_empty());
510 }
511
512 #[test]
513 fn default() {
514 let vec: ArrayVec<4, ()> = ArrayVec::default();
515 assert!(vec.is_empty());
516 }
517
518 #[test]
519 fn drop_empy() {
520 let x: ArrayVec<0, ()> = ArrayVec::new();
521 core::mem::drop(x);
522 }
523
524 #[test]
525 fn drop_heap_types() {
526 let x = ArrayVec::from_array([Box::new(0)]);
527 core::mem::drop(x);
528 let x = ArrayVec::from_array([String::from("I ♥ cum")]);
529 core::mem::drop(x);
530 let x = ArrayVec::from_array([vec![String::from("I ♥ you")]]);
531 core::mem::drop(x);
532 }
533
534 #[test]
535 fn clone() {
536 let vec = ArrayVec::from_array([1, 2, 3, 4]);
537 let mut vec2 = vec.clone();
538 assert_eq!(vec.as_slice(), vec2.as_slice());
539
540 vec2[1] = 69;
541 assert_eq!(vec[1], 2);
542 }
543
544 #[test]
545 fn len() {
546 const EXPECTED: [u32; 4] = [67, 69, 420, 80085];
547 let vec = ArrayVec::from_array(EXPECTED);
548 assert_eq!(vec.len(), EXPECTED.len());
549 }
550
551 #[test]
552 fn is_empty() {
553 let vec: ArrayVec<4, u8> = ArrayVec::new();
554 assert!(vec.is_empty());
555 }
556
557 #[test]
558 fn is_full() {
559 let vec: ArrayVec<4, u8> = ArrayVec::from_array([0; 4]);
560 assert!(vec.is_full());
561 }
562
563 #[test]
564 fn from_array() {
565 const EXPECTED: [u32; 4] = [67, 69, 420, 80085];
566 let vec = ArrayVec::from_array(EXPECTED);
567 assert_eq!(vec.as_slice(), EXPECTED);
568 }
569
570 #[test]
571 fn deref() {
572 let vec: ArrayVec<4, u8> = ArrayVec::from_array([0; 4]);
573 assert_eq!(&*vec, [0; 4]);
574 }
575
576 #[test]
577 fn deref_mut() {
578 let mut vec: ArrayVec<4, u8> = ArrayVec::from_array([0; 4]);
579 assert_eq!(&*vec, [0; 4]);
580
581 for item in &mut *vec {
582 *item = 10;
583 }
584 assert_eq!(&*vec, [10; 4]);
585 }
586
587 #[test]
588 fn from_slice() {
589 const EXPECTED: [u32; 4] = [67, 69, 420, 80085];
590 let vec = ArrayVec::<4, _>::from_slice(&EXPECTED).unwrap();
591 assert_eq!(vec.as_slice(), EXPECTED);
592 }
593
594 #[test]
595 #[should_panic]
596 fn from_slice_too_large() {
597 const EXPECTED: [u32; 4] = [67, 69, 420, 80085];
598 let _ = ArrayVec::<1, _>::from_slice(&EXPECTED).unwrap();
599 }
600
601 #[test]
602 fn as_array() {
603 let vec: ArrayVec<4, u8> = ArrayVec::from_array([69; 4]);
604 assert_eq!(&*vec, vec.as_array().unwrap());
605 }
606
607 #[test]
608 fn as_array_mut() {
609 let mut vec: ArrayVec<4, u8> = ArrayVec::from_array([69; 4]);
610 vec.as_array_mut().unwrap()[2] = 3;
611 assert_eq!(&*vec, [69, 69, 3, 69]);
612 }
613
614 #[test]
615 fn as_array_not_full() {
616 let vec: ArrayVec<4, u8> = ArrayVec::new();
617 assert_eq!(vec.as_array(), None);
618 }
619
620 #[test]
621 fn as_array_mut_not_full() {
622 let mut vec: ArrayVec<4, u8> = ArrayVec::new();
623 assert_eq!(vec.as_array_mut(), None);
624 }
625
626 #[test]
627 fn push() {
628 let mut vec: ArrayVec<5, u8> = ArrayVec::new();
629 vec.push(230);
630 assert_eq!(vec.as_slice(), &[230]);
631 vec.push(69);
632 assert_eq!(vec.as_slice(), &[230, 69]);
633 vec.push(101);
634 assert_eq!(vec.as_slice(), &[230, 69, 101]);
635 }
636
637 #[test]
638 #[should_panic]
639 fn push_beyond_capacity() {
640 let mut vec: ArrayVec<0, u8> = ArrayVec::new();
641 vec.push(69);
642 }
643
644 #[test]
645 fn pop_removes_values() {
646 let mut vec = ArrayVec::from_array([2, 3, 4]);
647 assert_eq!(vec.pop(), Some(4));
648 assert_eq!(&*vec, &[2, 3]);
649
650 assert_eq!(vec.pop(), Some(3));
651 assert_eq!(&*vec, &[2]);
652
653 assert_eq!(vec.pop(), Some(2));
654 assert_eq!(&*vec, &[]);
655
656 assert_eq!(vec.pop(), None);
657 assert_eq!(&*vec, &[]);
658 }
659
660 #[test]
661 fn pop_heap_types() {
662 let mut vec = ArrayVec::from_array([String::from("hey"), String::from("boy")]);
663 assert_eq!(vec.pop(), Some(String::from("boy")));
664 core::mem::drop(vec);
665 }
666
667 #[test]
668 fn push_pop() {
669 let mut vec = ArrayVec::<2, u8>::new();
670
671 vec.push(1);
672 assert_eq!(vec.pop(), Some(1));
673 assert_eq!(&*vec, &[]);
674
675 vec.push(8);
676 assert_eq!(vec.pop(), Some(8));
677 assert_eq!(&*vec, &[]);
678 }
679
680 #[test]
681 fn try_push_ok() {
682 let mut vec: ArrayVec<2, u8> = ArrayVec::new();
683 assert_eq!(vec.try_push(1), Ok(()));
684 assert_eq!(vec.try_push(2), Ok(()));
685 }
686
687 #[test]
688 fn try_push_full() {
689 let mut vec: ArrayVec<1, u8> = ArrayVec::new();
690 vec.push(1);
691 assert_eq!(vec.try_push(99), Err(99));
692 assert_eq!(vec.as_slice(), &[1]);
693 }
694
695 #[test]
696 fn try_insert() {
697 let mut vec: ArrayVec<4, u8> = ArrayVec::from_slice(&[1, 3]).unwrap();
698 assert_eq!(vec.try_insert(2, 1), Ok(()));
699 assert_eq!(vec.as_slice(), &[1, 2, 3]);
700 }
701
702 #[test]
703 fn try_insert_out_of_bounds() {
704 let mut vec: ArrayVec<4, u8> = ArrayVec::new();
705 assert!(vec.try_insert(0, 1).is_err());
706 }
707
708 #[test]
709 fn truncate() {
710 let mut vec = ArrayVec::from_array([1, 2, 3, 4]);
711
712 vec.truncate(2);
713 assert_eq!(vec.as_slice(), [1, 2]);
714 vec.push(0);
715 assert_eq!(vec.as_slice(), [1, 2, 0]);
716 vec.truncate(0);
717 assert_eq!(vec.as_slice(), []);
718 vec.truncate(0xcafebabe);
719 assert!(vec.is_empty());
720 }
721
722 #[test]
723 fn truncate_heap_types() {
724 let mut vec = ArrayVec::from_array([String::from("hey"), String::from("boy")]);
725
726 vec.truncate(1);
727 assert_eq!(vec.as_slice(), [String::from("hey")]);
728 core::mem::drop(vec);
729 }
730
731 #[test]
732 fn truncate_noop() {
733 let mut vec = ArrayVec::from_array([1, 2, 3, 4]);
734
735 vec.truncate(4);
737 assert_eq!(vec.len(), 4);
738 vec.truncate(10);
739 assert_eq!(vec.len(), 4);
740 }
741
742 #[test]
743 fn resize_truncate() {
744 let mut vec = ArrayVec::from_array([1, 2, 3, 4]);
745
746 vec.resize(2, 0);
747 assert_eq!(vec.len(), 2);
748 }
749
750 #[test]
751 #[should_panic]
752 fn resize_beyond_capacity() {
753 let mut vec = ArrayVec::<1, _>::from_slice(&[1]).unwrap();
754
755 vec.resize(2, 0);
756 }
757
758 #[test]
759 fn resize_extend_heap_types() {
760 let mut vec = ArrayVec::<1, _>::from_slice(&[]).unwrap();
761
762 vec.resize(1, String::from("girls rule"));
763 assert_eq!(vec.len(), 1);
764 assert_eq!(vec.as_slice(), [String::from("girls rule")]);
765 }
766
767 #[test]
768 fn insert() {
769 const EXPECTED: [u32; 4] = [67, 69, 420, 80085];
770 let vec: ArrayVec<4, u32> = {
771 let mut vec = ArrayVec::<4, _>::from_slice(&[67, 420, 80085]).unwrap();
772 vec.insert(69, 1);
773 vec
774 };
775 assert_eq!(vec.as_slice(), EXPECTED);
776 }
777
778 #[test]
779 #[should_panic]
780 fn insert_full() {
781 let mut vec = ArrayVec::<0, u64>::from_array([]);
782 vec.insert(0xcafebabe, 0);
783 }
784
785 proptest! {
786 #![proptest_config(proptest_config())]
787 #[test]
788 fn resize_extend(
789 initial in prop::collection::vec(0u8..=255, 0..4usize),
790 fill: u8,
791 extra in 0..5usize,
792 ) {
793 let new_len = initial.len() + extra;
794 let mut vec = ArrayVec::<8, u8>::from_slice(&initial).unwrap();
795 vec.resize(new_len, fill);
796
797 assert_eq!(&vec.as_slice()[..initial.len()], initial.as_slice());
798 assert!(vec.as_slice()[initial.len()..].iter().all(|&x| x == fill));
799 assert_eq!(vec.len(), new_len);
800 }
801 }
802
803 #[test]
804 fn ref_vec() {
805 let vec = ArrayVec::from_array([7; 4]);
806 let slice: ArrayVec<4, &i32> = vec.ref_vec();
807 assert!(vec.iter().zip(slice.iter().copied()).all(|(&l, r)| l.eq(r)));
808 }
809
810 #[test]
811 fn mut_vec() {
812 let mut vec = ArrayVec::from_array([7; 4]);
813 let slice: ArrayVec<4, &mut i32> = vec.mut_vec();
814
815 for x in slice {
816 *x = 69; }
818
819 assert_eq!(&*vec, [69; 4]);
820 }
821
822 #[test]
823 fn debug_noop() {
824 let vec = ArrayVec::from_array([1u8, 2, 3, 4]);
825 eprintln!("{vec:?}");
826 }
827
828 #[test]
829 fn partial_eq() {
830 let a = ArrayVec::from_array([1u8, 2, 3]);
831 let b = ArrayVec::from_array([1u8, 2, 3]);
832 let c = ArrayVec::from_array([1u8, 2, 4]);
833 assert_eq!(a, b);
834 assert_ne!(a, c);
835 }
836
837 #[test]
838 fn ord() {
839 let a = ArrayVec::from_array([1u8, 2, 3]);
840 let b = ArrayVec::from_array([1u8, 2, 4]);
841 assert!(a < b);
842 }
843
844 proptest! {
845 #![proptest_config(proptest_config())]
846 #[test]
847 fn shift_right_semantics(
848 original in prop::collection::vec(0u8..=255, 0..16),
849 item: u8,
850 ) {
851 let mut expected_slice = vec![item];
853 expected_slice.extend_from_slice(&original);
854 expected_slice.truncate(original.len()); let expected_returned = {
856 let mut full = vec![item];
857 full.extend_from_slice(&original);
858 full[original.len()..].to_vec() };
860
861 let mut buf = original.clone();
862 let returned = slice_shift_right(&mut buf, [item]);
863
864 assert_eq!(buf, expected_slice);
865 assert_eq!(returned, expected_returned.as_slice());
866 }
867 }
868
869 #[derive(Debug, Clone)]
870 enum Op {
871 Push(u8),
872 TryPush(u8),
873 Pop,
874 Insert(u8, usize),
875 TryInsert(u8, usize),
876 Truncate(usize),
877 Resize(usize, u8),
878 }
879
880 fn arbatrary_op() -> impl Strategy<Value = Op> {
881 prop_oneof![
882 any::<u8>().prop_map(Op::Push),
883 any::<u8>().prop_map(Op::TryPush),
884 Just(Op::Pop),
885 (any::<u8>(), any::<usize>()).prop_map(|(v, i)| Op::Insert(v, i)),
886 (any::<u8>(), any::<usize>()).prop_map(|(v, i)| Op::TryInsert(v, i)),
887 any::<usize>().prop_map(Op::Truncate),
888 (any::<u8>(), any::<usize>()).prop_map(|(v, i)| Op::Resize(i, v)),
889 ]
890 }
891
892 fn model_try_push(v: &mut Vec<u8>, value: u8) -> Result<(), u8> {
893 if v.len() >= v.capacity() {
894 return Err(value);
895 }
896
897 v.push(value);
898 Ok(())
899 }
900
901 fn model_try_insert(v: &mut Vec<u8>, value: u8, idx: usize) -> Result<(), u8> {
902 if v.len() >= v.capacity() || idx > v.len() {
903 return Err(value);
904 }
905
906 v.insert(idx, value);
907 Ok(())
908 }
909
910 proptest! {
911 #![proptest_config(proptest_config())]
912 #[test]
913 fn model_based(ops in prop::collection::vec(arbatrary_op(), 0..50)) {
914 const C: usize = 8;
915 let mut vec: ArrayVec<C, u8> = ArrayVec::new();
916 let mut model: Vec<u8> = Vec::with_capacity(C);
917
918 for op in ops {
919 match op {
920 Op::Push(v) => {
921 if model.len() < C {
922 vec.push(v);
923 model.push(v);
924 }
925 }
926 Op::TryPush(x) => {
927 assert_eq!(vec.try_push(x), model_try_push(&mut model, x));
928 }
929 Op::Pop => {
930 assert_eq!(vec.pop(), model.pop());
931 }
932 Op::Insert(v, i) => {
933 if model.len() < C {
934 let idx = i % (model.len() + 1);
935 vec.insert(v, idx);
936 model.insert(idx, v);
937 }
938 }
939 Op::TryInsert(val, idx) => {
940 assert_eq!(
941 vec.try_insert(val, idx),
942 model_try_insert(&mut model, val, idx)
943 );
944 }
945 Op::Truncate(n) => {
946 let n = n % (C + 1);
947 vec.truncate(n);
948 model.truncate(n);
949 }
950 Op::Resize(n, x) => {
951 let n = n % (C + 1);
952 vec.resize(n, x);
953 model.resize(n,x);
954 }
955 }
956 assert_eq!(vec.as_slice(), model.as_slice());
957 assert!(vec.len() <= C);
958 }
959 }
960 }
961}