1use core::fmt;
6use core::mem::MaybeUninit;
7
8#[cfg(creusot)]
9use creusot_std::prelude::*;
10pub use error::CapacityExceededError;
11pub use safety_boundary::ArrayVec;
12
13mod safety_boundary {
17 use core::mem::MaybeUninit;
18
19 #[cfg(creusot)]
20 use creusot_std::prelude::*;
21
22 #[derive(Copy)]
24 pub struct ArrayVec<T: Copy, const CAP: usize> {
25 len: usize,
26 data: [MaybeUninit<T>; CAP],
27 }
28
29 impl<T: Copy, const CAP: usize> ArrayVec<T, CAP> {
30 #[must_use]
32 pub const fn new() -> Self { Self { len: 0, data: [MaybeUninit::uninit(); CAP] } }
33
34 #[track_caller]
40 #[cfg_attr(creusot, check(ghost))]
41 #[cfg_attr(creusot, requires(slice@.len() <= CAP@))]
42 #[cfg_attr(creusot, ensures(result@ == slice@))]
43 pub const fn from_slice(slice: &[T]) -> Self {
44 assert!(slice.len() <= CAP);
45 let mut data = [MaybeUninit::uninit(); CAP];
46 let mut i = 0;
47 #[cfg_attr(creusot, invariant(forall<j> j >= 0 && j < i@ ==> data@[j]@ == Some(slice@[j])))]
49 #[cfg_attr(creusot, variant(slice@.len() - i@))]
50 while i < slice.len() {
51 data[i] = MaybeUninit::new(slice[i]);
52 i += 1;
53 }
54
55 Self { len: slice.len(), data }
56 }
57
58 #[cfg_attr(creusot, check(ghost))]
60 #[cfg_attr(creusot, ensures(self@ == result@))]
61 #[cfg_attr(creusot, ensures(result@.len() == self.len_view()))]
62 #[cfg_attr(creusot, ensures(forall<i> i >= 0 && i < self.len_view() ==> self.buf_view()[i]@ == Some((*result)@[i])))]
63 pub const fn as_slice(&self) -> &[T] {
64 unsafe {
66 if self.len > CAP {
67 core::hint::unreachable_unchecked()
68 }
69 super::slice_assume_init_ref(self.data.split_at(self.len).0)
70 }
71 }
72
73 #[cfg_attr(creusot, check(ghost))]
75 #[cfg_attr(creusot, ensures(result@.len() == self.len_view()))]
76 #[cfg_attr(creusot, ensures((*self)@.len() == (^self)@.len()))]
77 #[cfg_attr(creusot, ensures((*result)@.len() == (^result)@.len()))]
78 #[cfg_attr(creusot, ensures(self@ == result@))]
79 #[cfg_attr(creusot, ensures((^self)@ == (^result)@))]
80 #[cfg_attr(creusot, ensures(forall<i> i >= 0 && i < self.len_view() ==> (*self).buf_view()[i]@ == Some((*result)@[i]) && (^self).buf_view()[i]@ == Some((^result)@[i])))]
81 #[cfg_attr(creusot, ensures(forall<i> i >= self@.len() && i < CAP@ ==> (^self).buf_view()[i] == (*self).buf_view()[i]))]
82 pub fn as_mut_slice(&mut self) -> &mut [T] {
83 unsafe {
85 if self.len > CAP {
86 core::hint::unreachable_unchecked()
87 }
88 super::slice_assume_init_mut(self.data.split_at_mut(self.len).0)
89 }
90 }
91
92 #[cfg_attr(creusot, ensures((^self)@ == (*self)@))]
94 #[cfg_attr(creusot, ensures((*result)@.len() == CAP@ - self@.len()))]
95 #[cfg_attr(creusot, ensures((^result)@.len() == CAP@ - self@.len()))]
96 #[cfg_attr(creusot, ensures(forall<i> i >= 0 && i < CAP@ - self@.len() ==> (*result)[i] == (*self).buf_view()[self@.len() + i]))]
97 #[cfg_attr(creusot, ensures(forall<i> i >= 0 && i < CAP@ - self@.len() ==> (^result)[i] == (^self).buf_view()[self@.len() + i]))]
98 pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] {
99 unsafe { self.data.get_unchecked_mut(self.len..) }
101 }
102
103 #[cfg_attr(creusot, requires(new_len <= CAP))]
110 #[cfg_attr(creusot, requires(forall<i> i >= 0 && i < new_len@ ==> match (*self).buf_view()[i]@ { Some(x) => inv(x), None => false }))]
111 #[cfg_attr(creusot, ensures((^self)@.len() == new_len@))]
112 #[cfg_attr(creusot, ensures((^self).buf_view() == (*self).buf_view()))]
113 #[cfg_attr(creusot, ensures((^self).len_view() == new_len@))]
114 pub unsafe fn set_len(&mut self, new_len: usize) {
115 debug_assert!(new_len <= CAP);
116 self.len = new_len;
117 }
118
119 #[cfg(creusot)]
120 #[logic(inline)]
121 #[ensures(inv(self) ==> result.len() == CAP@)]
122 pub fn buf_view(self) -> Seq<MaybeUninit<T>> { self.data.view() }
123
124 #[cfg(creusot)]
125 #[logic]
126 #[ensures(inv(self) ==> result <= CAP@)]
127 pub fn len_view(self) -> Int { self.len.view() }
128 }
129
130 #[cfg(creusot)]
131 impl<T: Copy, const CAP: usize> Invariant for ArrayVec<T, CAP> {
132 #[logic(prophetic, inline)]
133 fn invariant(self) -> bool {
134 pearlite! {
135 self.len <= CAP && forall<i: Int> 0 <= i && i < self.len@ ==> match self.data@[i]@ { Some(x) => inv(x), None => false }
136 }
137 }
138 }
139
140 #[cfg(creusot)]
141 impl<T: Copy, const CAP: usize> View for ArrayVec<T, CAP> {
142 type ViewTy = Seq<T>;
143
144 #[logic(inline)]
145 #[ensures(inv(self) ==> result.len() <= CAP@)]
146 #[ensures(inv(self) ==> forall<i> i >= 0 && i < result.len() ==> self.buf_view()[i]@ == Some(result[i]))]
147 #[ensures(inv(self) ==> result.len() == self.len_view())]
148 fn view(self) -> Self::ViewTy {
149 pearlite! {
150 self.buf_view()
151 .subsequence(0, self.len@)
152 .map(|x: MaybeUninit<T>| {
153 match x@ {
154 Some(x) => x,
155 None => creusot_std::logic::any(),
156 }
157 })
158 }
159 }
160 }
161
162 #[cfg(creusot)]
163 impl<T: Copy + DeepModel, const CAP: usize> DeepModel for ArrayVec<T, CAP> {
164 type DeepModelTy = Seq<T::DeepModelTy>;
165
166 #[logic(open, inline)]
167 #[ensures(self@.len() == result.len())]
168 #[ensures(forall<i> 0 <= i && i < self@.len() ==> result[i] == self@[i].deep_model())]
169 fn deep_model(self) -> Self::DeepModelTy {
170 pearlite! {
171 self@.map(|x: T| x.deep_model())
172 }
173 }
174 }
175}
176
177#[cfg_attr(creusot, check(ghost))]
180#[cfg_attr(creusot, requires(forall<i> i >= 0 && i < slice@.len() ==> match slice[i]@ { Some(_) => true, None => false }))]
181#[cfg_attr(creusot, ensures(slice@.len() == result@.len()))]
182#[cfg_attr(creusot, ensures(forall<i> i >= 0 && i < slice@.len() ==> slice@[i]@ == Some(result@[i])))]
183const unsafe fn slice_assume_init_ref<T>(slice: &[MaybeUninit<T>]) -> &[T] {
184 #[cfg(creusot)]
185 {
186 unsafe { slice.assume_init_ref() }
188 }
189 #[cfg(not(creusot))]
190 {
191 unsafe { &*(slice as *const [MaybeUninit<T>] as *const [T]) }
194 }
195}
196
197#[cfg_attr(creusot, check(ghost))]
200#[cfg_attr(creusot, requires(forall<i> 0 <= i && i < slice@.len() ==> (*slice)[i]@ != None))]
201#[cfg_attr(creusot, ensures((*slice)@.len() == (*result)@.len()))]
202#[cfg_attr(creusot, ensures((^slice)@.len() == (^result)@.len()))]
203#[cfg_attr(creusot, ensures((*result)@.len() == (^result)@.len()))]
204#[cfg_attr(creusot, ensures(forall<i> 0 <= i && i < slice@.len() ==> (*slice)[i]@ == Some((*result)[i])))]
205#[cfg_attr(creusot, ensures(forall<i> 0 <= i && i < slice@.len() ==> (^slice)[i]@ == Some((^result)[i])))]
206unsafe fn slice_assume_init_mut<T>(slice: &mut [MaybeUninit<T>]) -> &mut [T] {
207 #[cfg(creusot)]
208 {
209 unsafe { slice.assume_init_mut() }
211 }
212 #[cfg(not(creusot))]
213 {
214 unsafe { &mut *(slice as *mut [MaybeUninit<T>] as *mut [T]) }
217 }
218}
219
220#[cfg_attr(creusot, check(ghost))]
222#[cfg_attr(creusot, requires(dest@.len() == src@.len()))]
223#[cfg_attr(creusot, ensures((^dest)@.len() == (*dest)@.len()))]
224#[cfg_attr(creusot, ensures(forall<i> i >= 0 && i < dest@.len() ==> (^dest)@[i]@ == Some(src[i])))]
225fn write_copy_of_slice<T: Copy>(dest: &mut [MaybeUninit<T>], src: &[T]) {
226 #[cfg(creusot)]
227 {
228 dest.write_copy_of_slice(src);
229 }
230 #[cfg(not(creusot))]
231 #[allow(clippy::transmute_ptr_to_ptr)]
233 {
234 let uninit_src: &[MaybeUninit<T>] = unsafe { core::mem::transmute(src) };
236 dest.copy_from_slice(uninit_src);
237 }
238}
239
240impl<T: Copy, const CAP: usize> ArrayVec<T, CAP> {
241 #[track_caller]
247 #[cfg_attr(creusot, requires(self@.len() < CAP@))]
248 #[cfg_attr(creusot, ensures((^self)@ == self@.push_back(element)))]
249 pub fn push(&mut self, element: T) {
250 self.try_push(element).expect("push past the capacity of the array");
251 }
252
253 #[cfg_attr(creusot, ensures(self@.len() < CAP@ ==> (^self)@ == self@.push_back(element) && result == Ok(())))]
259 #[cfg_attr(creusot, ensures(self@.len() == CAP@ ==> (^self)@ == (*self)@ && match result { Ok(()) => false, Err(_) => true }))]
260 pub fn try_push(&mut self, element: T) -> Result<(), CapacityExceededError> {
261 let first =
262 self.spare_capacity_mut().first_mut().ok_or(CapacityExceededError { capacity: CAP })?;
263 *first = MaybeUninit::new(element);
264 let old_len = self.len();
265 unsafe {
270 self.set_len(old_len + 1);
271 }
272 Ok(())
273 }
274
275 #[cfg_attr(creusot, ensures(self@.len() == 0 ==> result == None))]
279 #[cfg_attr(creusot, ensures(self@.len() == 0 ==> (^self) == (*self)))]
280 #[cfg_attr(creusot, ensures(self@.len() > 0 ==> result == Some(self@[self@.len() - 1])))]
281 #[cfg_attr(creusot, ensures(self@.len() > 0 ==> (^self)@ == (*self)@.subsequence(0, (*self)@.len() - 1)))]
282 pub fn pop(&mut self) -> Option<T> {
283 let slice = self.as_slice();
284 let res = *slice.last()?;
285 let old_len = slice.len();
286 unsafe { self.set_len(old_len - 1) }
290 Some(res)
291 }
292
293 #[track_caller]
299 #[cfg_attr(creusot, requires(slice@.len() <= CAP@ - self@.len()))]
300 #[cfg_attr(creusot, ensures((^self)@ == (*self)@.concat(slice@)))]
301 pub fn extend_from_slice(&mut self, slice: &[T]) {
302 let dst = self.spare_capacity_mut().get_mut(..slice.len()).expect("buffer overflow");
303 write_copy_of_slice(dst, slice);
304 let old_len = self.len();
305 unsafe { self.set_len(old_len + slice.len()) }
306 }
307}
308
309impl<T: Copy, const CAP: usize> Default for ArrayVec<T, CAP> {
310 fn default() -> Self { Self::new() }
311}
312
313#[allow(clippy::non_canonical_clone_impl)]
318#[allow(clippy::expl_impl_clone_on_copy)]
319impl<T: Copy, const CAP: usize> Clone for ArrayVec<T, CAP> {
320 #[cfg_attr(creusot, ensures(result@ == self@))]
321 fn clone(&self) -> Self { Self::from_slice(self) }
322}
323
324impl<T: Copy, const CAP: usize> core::ops::Deref for ArrayVec<T, CAP> {
325 type Target = [T];
326
327 #[cfg_attr(creusot, check(ghost))]
328 #[cfg_attr(creusot, ensures(self@ == result@))]
329 #[cfg_attr(creusot, ensures(result@.len() == self.len_view()))]
330 #[cfg_attr(creusot, ensures(forall<i> i >= 0 && i < self.len_view() ==> self.buf_view()[i]@ == Some((*result)@[i])))]
331 fn deref(&self) -> &Self::Target { self.as_slice() }
332}
333
334impl<T: Copy, const CAP: usize> core::ops::DerefMut for ArrayVec<T, CAP> {
335 #[cfg_attr(creusot, check(ghost))]
336 #[cfg_attr(creusot, ensures(result@.len() == self.len_view()))]
337 #[cfg_attr(creusot, ensures((*self)@.len() == (^self)@.len()))]
338 #[cfg_attr(creusot, ensures((*result)@.len() == (^result)@.len()))]
339 #[cfg_attr(creusot, ensures(self@ == result@))]
340 #[cfg_attr(creusot, ensures((^self)@ == (^result)@))]
341 #[cfg_attr(creusot, ensures(forall<i> i >= 0 && i < self.len_view() ==> (*self).buf_view()[i]@ == Some((*result)@[i]) && (^self).buf_view()[i]@ == Some((^result)@[i])))]
342 #[cfg_attr(creusot, ensures(forall<i> i >= self@.len() && i < CAP@ ==> (^self).buf_view()[i] == (*self).buf_view()[i]))]
343 fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut_slice() }
344}
345
346macro_rules! with_deep_model {
347 ($(impl<$param:ident: $bound:ident $(+ $bounds:ident)*, const $cap:ident: usize $(, const $cap2:ident: usize)?> $tr:ident$(<$trait_ty:ty>)? for $ty:ty $(where $wherety:ty: $wheretr:path)? { $($imp:tt)* })*) => {
348 $(
349 #[cfg(creusot)]
350 impl<$param: $bound $(+ $bounds)* + DeepModel, const $cap: usize $(, const $cap2: usize)?> $tr $(<$trait_ty>)? for $ty $(where $wherety: $wheretr)? {
351 $($imp)*
352 }
353
354 #[cfg(not(creusot))]
355 impl<$param: $bound $(+ $bounds)*, const $cap: usize $(, const $cap2: usize)?> $tr$(<$trait_ty>)? for $ty {
356 $($imp)*
357 }
358 )*
359 }
360}
361
362with_deep_model! {
363impl<T: Copy + Eq, const CAP: usize> Eq for ArrayVec<T, CAP> {}
364
365impl<T: Copy + PartialEq, const CAP1: usize, const CAP2: usize> PartialEq<ArrayVec<T, CAP2>>
366 for ArrayVec<T, CAP1>
367{
368 #[cfg_attr(creusot, ensures(result == (self.deep_model() == other.deep_model())))]
369 fn eq(&self, other: &ArrayVec<T, CAP2>) -> bool {
370 **self == **other
371 }
372}
373
374impl<T: Copy + PartialEq, const CAP: usize> PartialEq<[T]> for ArrayVec<T, CAP> {
375 #[cfg_attr(creusot, ensures(result == (self.deep_model() == other.deep_model())))]
376 fn eq(&self, other: &[T]) -> bool { **self == *other }
377}
378
379impl<T: Copy + PartialEq, const CAP: usize> PartialEq<ArrayVec<T, CAP>> for [T] {
380 #[cfg_attr(creusot, ensures(result == (self.deep_model() == other.deep_model())))]
381 fn eq(&self, other: &ArrayVec<T, CAP>) -> bool { *self == **other }
382}
383
384impl<T: Copy + PartialEq, const CAP: usize, const LEN: usize> PartialEq<[T; LEN]>
385 for ArrayVec<T, CAP>
386{
387 #[cfg_attr(creusot, ensures(result == (self.deep_model() == other.deep_model())))]
388 fn eq(&self, other: &[T; LEN]) -> bool { other == self }
389}
390
391impl<T: Copy + PartialEq, const CAP: usize, const LEN: usize> PartialEq<ArrayVec<T, CAP>>
392 for [T; LEN]
393{
394 #[cfg_attr(creusot, ensures(result == (self.deep_model() == other.deep_model())))]
395 fn eq(&self, other: &ArrayVec<T, CAP>) -> bool { *self == **other }
396}
397
398impl<T: Copy + Ord, const CAP: usize> Ord for ArrayVec<T, CAP> where T::DeepModelTy: OrdLogic {
399 #[cfg_attr(creusot, ensures(result == (*self).deep_model().cmp_log((*other).deep_model())))]
400 fn cmp(&self, other: &Self) -> core::cmp::Ordering { (**self).cmp(&**other) }
401}
402
403impl<T: Copy + PartialOrd, const CAP1: usize, const CAP2: usize> PartialOrd<ArrayVec<T, CAP2>>
404 for ArrayVec<T, CAP1> where T::DeepModelTy: PartialOrdLogic {
405 #[cfg_attr(creusot, ensures(result == (*self).deep_model().partial_cmp_log((*other).deep_model())))]
406 fn partial_cmp(&self, other: &ArrayVec<T, CAP2>) -> Option<core::cmp::Ordering> {
407 let left = &**self;
408 let right = &**other;
409 #[cfg(creusot)]
410 {
411 proof_assert!(left.deep_model() == self.deep_model());
413 proof_assert!(other.deep_model() == right.deep_model());
414 }
415 left.partial_cmp(right)
416 }
417}
418}
419
420impl<T: Copy + fmt::Debug, const CAP: usize> fmt::Debug for ArrayVec<T, CAP> {
421 #[cfg_attr(creusot, requires(false))]
422 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&**self, f) }
423}
424
425impl<T: Copy + core::hash::Hash, const CAP: usize> core::hash::Hash for ArrayVec<T, CAP> {
426 #[cfg_attr(creusot, requires(false))]
427 fn hash<H: core::hash::Hasher>(&self, state: &mut H) { core::hash::Hash::hash(&**self, state); }
428}
429
430pub mod error {
432 use core::fmt;
433
434 #[cfg(creusot)]
435 use creusot_std::prelude::*;
436 #[cfg(creusot)]
437 use creusot_std::prelude::{Clone, PartialEq};
438
439 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
441 pub struct CapacityExceededError {
442 pub(super) capacity: usize,
444 }
445
446 impl fmt::Display for CapacityExceededError {
447 #[cfg_attr(creusot, requires(false))]
448 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
449 write!(f, "Capacity exceeded: {}", self.capacity)
450 }
451 }
452
453 #[cfg(feature = "std")]
454 impl std::error::Error for CapacityExceededError {
455 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
456 let Self { capacity: _ } = self;
457 None
458 }
459 }
460
461 #[cfg(creusot)]
462 impl DeepModel for CapacityExceededError {
463 type DeepModelTy = Self;
464
465 #[logic]
466 fn deep_model(self) -> Self::DeepModelTy { self }
467 }
468}
469
470#[cfg(feature = "serde")]
471impl<T: Copy + crate::serde::Serialize, const CAP: usize> crate::serde::Serialize
472 for ArrayVec<T, CAP>
473{
474 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
475 where
476 S: crate::serde::Serializer,
477 {
478 serializer.collect_seq(self.iter())
479 }
480}
481
482#[cfg(feature = "serde")]
483impl<'de, T, const CAP: usize> crate::serde::Deserialize<'de> for ArrayVec<T, CAP>
484where
485 T: Copy + crate::serde::Deserialize<'de>,
486{
487 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
488 where
489 D: serde::Deserializer<'de>,
490 {
491 use core::marker::PhantomData;
492
493 use crate::serde::de;
494
495 struct Visitor<T, const CAP: usize>(PhantomData<T>);
496
497 impl<'de, T, const CAP: usize> de::Visitor<'de> for Visitor<T, CAP>
498 where
499 T: Copy + crate::serde::Deserialize<'de>,
500 {
501 type Value = ArrayVec<T, CAP>;
502
503 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
504 write!(f, "a sequence of at most {} elements", CAP)
505 }
506
507 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
508 where
509 A: de::SeqAccess<'de>,
510 {
511 use de::Error;
512
513 if let Some(hint) = seq.size_hint() {
514 if hint > CAP {
515 return Err(Error::invalid_length(hint, &self));
516 }
517 }
518
519 let mut out = ArrayVec::<T, CAP>::new();
520 while let Some(elem) = seq.next_element::<T>()? {
521 out.try_push(elem).map_err(|_| Error::invalid_length(out.len() + 1, &self))?;
522 }
523 Ok(out)
524 }
525 }
526 deserializer.deserialize_seq(Visitor::<T, CAP>(PhantomData))
527 }
528}
529
530#[cfg(test)]
531mod tests {
532 use super::ArrayVec;
533
534 #[test]
535 fn arrayvec_ops() {
536 let mut av = ArrayVec::<_, 1>::new();
537 assert!(av.is_empty());
538 av.push(42);
539 assert_eq!(av.len(), 1);
540 assert_eq!(av, [42]);
541 }
542
543 #[test]
544 #[should_panic(expected = "push past the capacity of the array")]
545 fn overflow_push() {
546 let mut av = ArrayVec::<_, 0>::new();
547 av.push(42);
548 }
549
550 #[test]
551 #[should_panic(expected = "buffer overflow")]
552 fn overflow_extend() {
553 let mut av = ArrayVec::<_, 0>::new();
554 av.extend_from_slice(&[42]);
555 }
556
557 #[test]
558 fn extend_from_slice() {
559 let mut av = ArrayVec::<u8, 8>::new();
560 av.extend_from_slice(b"abc");
561 }
562
563 #[cfg(feature = "serde")]
564 #[test]
565 fn serde_round_trip_u8() {
566 let mut want = ArrayVec::<u8, 8>::new();
567 want.extend_from_slice(b"abc");
568
569 let json = serde_json::to_string(&want).expect("serde_json failed to encode");
570 let got: ArrayVec<u8, 8> =
571 serde_json::from_str(&json).expect("serde_json failed to decode");
572 assert_eq!(got, want);
573
574 let bin = bincode::serialize(&want).expect("bincode failed to encode");
575 let got: ArrayVec<u8, 8> = bincode::deserialize(&bin).expect("bincode failed to decode");
576 assert_eq!(got, want);
577 }
578
579 #[cfg(feature = "serde")]
580 #[test]
581 fn serde_round_trip_u32() {
582 let mut want = ArrayVec::<u32, 4>::new();
583 (1..=3).for_each(|i| want.push(i));
584
585 let json = serde_json::to_string(&want).expect("serde_json failed to encode");
586 let got: ArrayVec<u32, 4> =
587 serde_json::from_str(&json).expect("serde_json failed to decode");
588 assert_eq!(got, want);
589
590 let bin = bincode::serialize(&want).expect("bincode failed to encode");
591 let got: ArrayVec<u32, 4> = bincode::deserialize(&bin).expect("bincode failed to decode");
592 assert_eq!(got, want);
593 }
594
595 #[cfg(feature = "serde")]
596 #[test]
597 fn serde_round_trip_empty() {
598 let want = ArrayVec::<u8, 0>::new();
599
600 let json = serde_json::to_string(&want).expect("serde_json failed to encode");
601 assert_eq!(json, "[]");
602 let got: ArrayVec<u8, 0> =
603 serde_json::from_str(&json).expect("serde_json failed to decode");
604 assert_eq!(got, want);
605 }
606
607 #[cfg(feature = "serde")]
608 #[test]
609 fn serde_deserialize_overflow_json_returns_error() {
610 let json = "[1,2,3]";
613 let res: Result<ArrayVec<u8, 2>, _> = serde_json::from_str(json);
614 assert!(res.is_err(), "expected an error for over-capacity input");
615 }
616
617 #[cfg(feature = "serde")]
618 #[test]
619 fn serde_deserialize_overflow_bincode_returns_error() {
620 let slice: &[u8] = &[1, 2, 3];
623 let bin = bincode::serialize(slice).expect("bincode failed to encode");
624 let res: Result<ArrayVec<u8, 2>, _> = bincode::deserialize(&bin);
625 assert!(res.is_err(), "expected an error for over-capacity input");
626 }
627
628 #[cfg(feature = "serde")]
629 #[test]
630 fn serde_matches_vec_wire_format() {
631 let slice: &[u8] = &[1, 2, 3];
634 let want = ArrayVec::<u8, 8>::from_slice(slice);
635
636 let av_json = serde_json::to_string(&want).expect("serde_json failed to encode");
638 let slice_json = serde_json::to_string(slice).expect("serde_json failed to encode");
639 assert_eq!(av_json, slice_json);
640
641 let av_bin = bincode::serialize(&want).expect("bincode failed to encode");
643 let slice_bin = bincode::serialize(slice).expect("bincode failed to encode");
644 assert_eq!(av_bin, slice_bin);
645
646 let got: ArrayVec<u8, 8> =
648 serde_json::from_str(&slice_json).expect("serde_json failed to decode");
649 assert_eq!(got, want);
650
651 let got: ArrayVec<u8, 8> =
652 bincode::deserialize(&slice_bin).expect("bincode failed to decode");
653 assert_eq!(got, want);
654 }
655}
656
657#[cfg(kani)]
658mod verification {
659 use super::*;
660
661 #[kani::unwind(16)] #[kani::proof]
663 fn no_out_of_bounds_less_than_cap() {
664 const CAP: usize = 32;
665 let n = kani::any::<u32>();
666 let elements = (n & 0x0F) as usize; let val = kani::any::<u32>();
669
670 let mut v = ArrayVec::<u32, CAP>::new();
671 for _ in 0..elements {
672 v.push(val);
673 }
674
675 for i in 0..elements {
676 assert_eq!(v[i], val);
677 }
678 }
679
680 #[kani::unwind(16)] #[kani::proof]
682 fn no_out_of_bounds_upto_cap() {
683 const CAP: usize = 15;
684 let elements = CAP;
685
686 let val = kani::any::<u32>();
687
688 let mut v = ArrayVec::<u32, CAP>::new();
689 for _ in 0..elements {
690 v.push(val);
691 }
692
693 for i in 0..elements {
694 assert_eq!(v[i], val);
695 }
696 }
697}