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