1use core::marker::Destruct;
2use core::mem::MaybeUninit;
3use core::ops;
4use core::ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive};
5
6use super::ArrayVec;
7
8pub(crate) const fn write_filled_const<T: [const] Clone + [const] Destruct>(
9 slice: &mut [MaybeUninit<T>],
10 value: T,
11) {
12 if slice.is_empty() {
13 return;
14 }
15
16 konst::iter::for_each! { elem in konst::slice::get_up_to_mut(slice, slice.len().wrapping_sub(1)).unwrap() =>
19 elem.write(value.clone());
20 }
21 slice[slice.len().wrapping_sub(1)].write(value);
22}
23
24impl<const C: usize, T> const ops::Deref for ArrayVec<C, T> {
25 type Target = [T];
26
27 #[inline]
28 fn deref(&self) -> &Self::Target { self.as_slice() }
29}
30
31impl<const C: usize, T> const ops::DerefMut for ArrayVec<C, T> {
32 #[inline]
33 fn deref_mut(&mut self) -> &mut Self::Target { self.as_slice_mut() }
34}
35
36macro_rules! impl_index {
37 ($($types:ty => $output:ty),+) => {
38 $(
39 impl<const C: usize, T> const ops::Index<$types> for ArrayVec<C, T> {
40 type Output = $output;
41
42 #[inline]
43 fn index(&self, index: $types) -> &Self::Output { &self.as_slice()[index] }
44 }
45
46 impl<const C: usize,T> const ops::IndexMut<$types> for ArrayVec<C, T> {
47 #[inline]
48 fn index_mut(&mut self, index: $types) -> &mut Self::Output { &mut self.as_slice_mut()[index] }
49 }
50 )+
51 }
52}
53impl_index!(
54 usize => T,
55 Range<usize> => [T],
56 RangeInclusive<usize> => [T],
57 RangeTo<usize> => [T],
58 RangeToInclusive<usize> => [T],
59 RangeFrom<usize> => [T],
60 RangeFull => [T]
61);
62
63impl<const C: usize, T> const Default for ArrayVec<C, T> {
64 #[inline]
65 fn default() -> Self { Self::new() }
66}
67
68impl<const C: usize, T: PartialEq> PartialEq for ArrayVec<C, T> {
69 #[inline]
70 default fn eq(&self, other: &ArrayVec<C, T>) -> bool {
71 self.len() == other.len() && self.as_slice().eq(other.as_slice())
72 }
73}
74
75impl<const C: usize, T: [const] PartialEq> const PartialEq for ArrayVec<C, T> {
76 #[inline]
77 fn eq(&self, other: &ArrayVec<C, T>) -> bool {
78 self.len() == other.len() && self.as_slice().eq(other.as_slice())
79 }
80}
81
82impl<const C: usize, T: [const] Eq> const Eq for ArrayVec<C, T> {}
83
84impl<const C: usize, T: PartialOrd> PartialOrd for ArrayVec<C, T> {
85 #[inline]
86 default fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
87 self.as_slice().partial_cmp(other.as_slice())
88 }
89}
90
91impl<const C: usize, T: [const] PartialOrd> const PartialOrd for ArrayVec<C, T> {
92 #[inline]
93 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
94 self.as_slice().partial_cmp(other.as_slice())
95 }
96}
97
98impl<const C: usize, T: Ord> Ord for ArrayVec<C, T> {
99 #[inline]
100 default fn cmp(&self, other: &Self) -> core::cmp::Ordering { self.as_slice().cmp(other.as_slice()) }
101}
102
103impl<const C: usize, T: [const] Ord> const Ord for ArrayVec<C, T> {
104 #[inline]
105 fn cmp(&self, other: &Self) -> core::cmp::Ordering { self.as_slice().cmp(other.as_slice()) }
106}
107
108impl<const C: usize, T> ArrayVec<C, T> {
109 #[inline]
111 pub const fn from_slice_const(slice: &[T]) -> Option<Self>
112 where
113 T: const Clone, {
114 if slice.len() > C {
115 return None;
116 }
117
118 let mut array = konst::maybe_uninit::UNINIT_ARRAY::<T, C>::V;
119
120 konst::iter::for_each! {idx in 0..slice.len() =>
121 let item = slice[idx].clone();
122 array[idx] = MaybeUninit::new(item);
123 }
124
125 Some(Self {
126 array,
127 len: slice.len(),
128 })
129 }
130
131 #[inline]
133 pub const fn truncate_const(&mut self, len: usize)
134 where
135 T: [const] Destruct, {
136 if len >= self.len {
137 return;
138 }
139
140 unsafe { self.array[len..self.len].assume_init_drop() };
144 self.len = len;
145 }
146
147 #[inline]
155 pub const fn resize_const(&mut self, new_len: usize, value: T)
156 where
157 T: [const] Clone + [const] Destruct, {
158 assert!(new_len <= C, "Tried to resize beyond capacity.");
159
160 if new_len < self.len {
161 self.truncate_const(new_len);
162 } else if new_len > self.len {
163 write_filled_const(&mut self.array[self.len..new_len], value);
164 self.len = new_len;
165 }
166 }
167}
168
169#[cfg(test)]
170#[cfg_attr(coverage_nightly, coverage(off))]
171mod tests {
172
173 use super::*;
174 use proptest::prelude::*;
175
176 fn proptest_config() -> ProptestConfig {
177 ProptestConfig {
178 #[cfg(miri)]
179 failure_persistence: None,
180 #[cfg(miri)]
181 cases: 32,
182 ..ProptestConfig::default()
183 }
184 }
185
186 #[test]
187 fn const_partial_eq() {
188 static A: ArrayVec<3, u8> = ArrayVec::from_array([1u8, 2, 3]);
189 static B: ArrayVec<3, u8> = ArrayVec::from_array([1u8, 2, 3]);
190 static C: ArrayVec<3, u8> = ArrayVec::from_array([1u8, 2, 4]);
191
192 assert_eq!(A, B);
193 assert_ne!(A, C);
194 }
195
196 #[test]
197 fn const_ord() {
198 static A: ArrayVec<3, u8> = ArrayVec::from_array([1u8, 2, 3]);
199 static B: ArrayVec<3, u8> = ArrayVec::from_array([1u8, 2, 4]);
200 assert!(A < B);
201 }
202
203 #[test]
204 fn write_filled_const_empty() {
205 let mut vec: ArrayVec<0, ()> = ArrayVec::default();
206 write_filled_const(&mut vec.array, ());
207 assert!(vec.is_empty());
208 }
209
210 #[test]
211 fn from_slice_const() {
212 const EXPECTED: [u32; 4] = [67, 69, 420, 80085];
213 let vec: ArrayVec<4, u32> = ArrayVec::<4, _>::from_slice_const(&EXPECTED).unwrap();
214 assert_eq!(vec.as_slice(), EXPECTED);
215 }
216
217 #[test]
218 fn from_slice_overflow() {
219 assert!(ArrayVec::<4, u32>::from_slice_const(&[1; 8]).is_none());
220 }
221
222 #[test]
223 fn truncate_const() {
224 let mut vec = ArrayVec::from_array([1, 2, 3, 4]);
225
226 vec.truncate_const(2);
227 assert_eq!(vec.as_slice(), [1, 2]);
228 vec.push(0);
229 assert_eq!(vec.as_slice(), [1, 2, 0]);
230 vec.truncate_const(0);
231 assert_eq!(vec.as_slice(), []);
232 vec.truncate_const(0xcafebabe);
233 assert!(vec.is_empty());
234 }
235
236 #[test]
237 fn truncate_const_heap_types() {
238 let mut vec = ArrayVec::from_array([String::from("hey"), String::from("boy")]);
239
240 vec.truncate_const(1);
241 assert_eq!(vec.as_slice(), [String::from("hey")]);
242 core::mem::drop(vec);
243 }
244
245 #[test]
246 fn truncate_const_noop() {
247 let mut vec = ArrayVec::from_array([1, 2, 3, 4]);
248
249 vec.truncate_const(4);
251 assert_eq!(vec.len(), 4);
252 vec.truncate_const(10);
253 assert_eq!(vec.len(), 4);
254 }
255
256 #[derive(Debug, Clone)]
257 enum Op {
258 Push(u8),
259 TryPush(u8),
260 Pop,
261 Insert(u8, usize),
262 TryInsert(u8, usize),
263 Truncate(usize),
264 Resize(usize, u8),
265 TruncateConst(usize),
266 ResizeConst(usize, u8),
267 }
268
269 fn arbatrary_op() -> impl Strategy<Value = Op> {
270 prop_oneof![
271 any::<u8>().prop_map(Op::Push),
272 any::<u8>().prop_map(Op::TryPush),
273 Just(Op::Pop),
274 (any::<u8>(), any::<usize>()).prop_map(|(v, i)| Op::Insert(v, i)),
275 (any::<u8>(), any::<usize>()).prop_map(|(v, i)| Op::TryInsert(v, i)),
276 any::<usize>().prop_map(Op::Truncate),
277 (any::<u8>(), any::<usize>()).prop_map(|(v, i)| Op::Resize(i, v)),
278 any::<usize>().prop_map(Op::TruncateConst),
279 (any::<u8>(), any::<usize>()).prop_map(|(v, i)| Op::ResizeConst(i, v)),
280 ]
281 }
282
283 fn model_try_push(v: &mut Vec<u8>, value: u8) -> Result<(), u8> {
284 if v.len() >= v.capacity() {
285 return Err(value);
286 }
287
288 v.push(value);
289 Ok(())
290 }
291
292 fn model_try_insert(v: &mut Vec<u8>, value: u8, idx: usize) -> Result<(), u8> {
293 if v.len() >= v.capacity() || idx > v.len() {
294 return Err(value);
295 }
296
297 v.insert(idx, value);
298 Ok(())
299 }
300
301 proptest! {
302 #![proptest_config(proptest_config())]
303 #[test]
304 fn model_based(ops in prop::collection::vec(arbatrary_op(), 0..50)) {
305 const C: usize = 8;
306 let mut vec: ArrayVec<C, u8> = ArrayVec::new();
307 let mut model: Vec<u8> = Vec::with_capacity(C);
308
309 for op in ops {
310 match op {
311 Op::Push(v) => {
312 if model.len() < C {
313 vec.push(v);
314 model.push(v);
315 }
316 }
317 Op::TryPush(x) => {
318 assert_eq!(vec.try_push(x), model_try_push(&mut model, x));
319 }
320 Op::Pop => {
321 assert_eq!(vec.pop(), model.pop());
322 }
323 Op::Insert(v, i) => {
324 if model.len() < C {
325 let idx = i % (model.len() + 1);
326 vec.insert(v, idx);
327 model.insert(idx, v);
328 }
329 }
330 Op::TryInsert(val, idx) => {
331 assert_eq!(
332 vec.try_insert(val, idx),
333 model_try_insert(&mut model, val, idx)
334 );
335 }
336 Op::Truncate(n) => {
337 let n = n % (C + 1);
338 vec.truncate(n);
339 model.truncate(n);
340 }
341 Op::Resize(n, x) => {
342 let n = n % (C + 1);
343 vec.resize(n, x);
344 model.resize(n,x);
345 }
346 Op::TruncateConst(n) => {
347 let n = n % (C + 1);
348 vec.truncate_const(n);
349 model.truncate(n);
350 }
351 Op::ResizeConst(n, x) => {
352 let n = n % (C + 1);
353 vec.resize_const(n, x);
354 model.resize(n,x);
355 }
356 }
357 assert_eq!(vec.as_slice(), model.as_slice());
358 assert!(vec.len() <= C);
359 }
360 }
361 }
362}