combo_vec/re_arr.rs
1#[cfg(feature = "alloc")]
2use alloc::{
3 string::{String, ToString},
4 vec::Vec,
5};
6
7use core::{
8 array::IntoIter as ArrayIter,
9 cmp::Ordering,
10 fmt::{Debug, Display, Formatter, Result as FmtResult},
11 hash::{Hash, Hasher},
12 iter::Flatten,
13 ops,
14};
15
16/// Easy way to create a new [`ReArr`] with elements.
17///
18/// ## Examples
19///
20/// ```rust
21/// use combo_vec::{re_arr, ReArr};
22///
23/// const SOME_ITEMS: ReArr<i8, 3> = re_arr![1, 2, 3];
24/// const MANY_ITEMS: ReArr<u16, 90> = re_arr![5; 90];
25/// const EXTRA_ITEMS: ReArr<&str, 5> = re_arr!["Hello", "world", "!"; None, None];
26///
27/// // Infer the type and size of the ReArr
28/// const NO_STACK_F32: ReArr<f32, 0> = re_arr![];
29///
30/// // No const-initialization is needed to create a ComboVec with allocated elements on the stack
31/// use std::collections::HashMap;
32/// const EMPTY_HASHMAP_ALLOC: ReArr<HashMap<&str, i32>, 3> = re_arr![];
33///
34/// // Creating a new ReArr at compile time and doing this does have performance benefits
35/// let my_re_arr = EMPTY_HASHMAP_ALLOC;
36/// ```
37#[macro_export]
38macro_rules! re_arr {
39 () => (
40 $crate::ReArr::new()
41 );
42 ($elem:expr; $n:expr) => (
43 $crate::ReArr::from_arr([Some($elem); $n])
44 );
45 ($($x:expr),+ $(,)?) => (
46 $crate::ReArr::from_arr([$(Some($x)),+])
47 );
48 ($($x:expr),+; $($rest:expr),* $(,)?) => (
49 $crate::ReArr::from_arr([$(Some($x)),+, $($rest),*])
50 );
51}
52
53/// A [`ReArr`] is a fixed-size array with a variable number of elements.
54///
55/// Create a new [`ReArr`] using the [`re_arr!`] macro.
56///
57/// ## Examples
58///
59/// ```rust
60/// use combo_vec::{re_arr, ReArr};
61///
62/// const SOME_ITEMS: ReArr<i8, 3> = re_arr![1, 2, 3];
63/// const MANY_ITEMS: ReArr<u16, 90> = re_arr![5; 90];
64///
65/// // Infer the type and size of the ReArr
66/// const NO_STACK_F32: ReArr<f32, 0> = re_arr![];
67///
68/// // No const-initialization is needed to create a ReArr with allocated elements on the stack
69/// use std::collections::HashMap;
70/// const EMPTY_HASHMAP_ALLOC: ReArr<HashMap<&str, i32>, 3> = re_arr![];
71///
72/// let mut my_re_arr = re_arr![1, 2, 3; None, None];
73/// // Allocate an extra element on the heap
74/// my_re_arr.push(4);
75/// assert_eq!(my_re_arr.len(), 4);
76/// // Truncate to only the first 2 elements
77/// my_re_arr.truncate(2);
78/// assert_eq!(my_re_arr.len(), 2);
79/// // Fill the last element on the stack, then allocate the next two items on the heap
80/// my_re_arr.extend([3, 4, 5]);
81/// ```
82pub struct ReArr<T, const N: usize> {
83 pub(crate) arr: [Option<T>; N],
84 arr_len: usize,
85}
86
87impl<T: Clone, const N: usize> Clone for ReArr<T, N> {
88 #[inline]
89 fn clone(&self) -> Self {
90 Self {
91 arr: self.arr.clone(),
92 arr_len: self.arr_len,
93 }
94 }
95}
96
97impl<T: PartialOrd, const N: usize> PartialOrd for ReArr<T, N> {
98 #[inline]
99 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
100 self.iter().partial_cmp(other.iter())
101 }
102}
103
104impl<T: Ord, const N: usize> Ord for ReArr<T, N> {
105 #[inline]
106 fn cmp(&self, other: &Self) -> Ordering {
107 self.iter().cmp(other.iter())
108 }
109}
110
111impl<T: PartialEq, const N: usize> PartialEq for ReArr<T, N> {
112 #[inline]
113 fn eq(&self, other: &Self) -> bool {
114 self.iter().eq(other.iter())
115 }
116}
117
118impl<T: PartialEq + Eq, const N: usize> Eq for ReArr<T, N> {}
119
120impl<T: Hash, const N: usize> Hash for ReArr<T, N> {
121 #[inline]
122 fn hash<H: Hasher>(&self, state: &mut H) {
123 self.iter().for_each(|x| x.hash(state));
124 }
125}
126
127impl<T, const N: usize> Default for ReArr<T, N> {
128 #[inline]
129 fn default() -> Self {
130 Self::new()
131 }
132}
133
134impl<T, const N: usize> ReArr<T, N> {
135 const DEFAULT_ARR_VALUE: Option<T> = None;
136
137 /// Create a new, empty [`ReArr`] with the ability for `N` element to stored on the stack.
138 ///
139 /// This is used by the [`re_arr!`] macro, and you should consider using it instead.
140 ///
141 /// ## Examples
142 ///
143 /// ```rust
144 /// use combo_vec::{re_arr, ReArr};
145 ///
146 /// const RE_ARR: ReArr::<i32, 3> = re_arr![];
147 /// let my_re_arr = ReArr::<i32, 3>::new();
148 /// assert_eq!(my_re_arr, RE_ARR);
149 /// ```
150 #[must_use]
151 #[inline]
152 pub const fn new() -> Self {
153 Self {
154 arr: [Self::DEFAULT_ARR_VALUE; N],
155 arr_len: 0,
156 }
157 }
158
159 /// Create a new [`ReArr`] from an array.
160 ///
161 /// All slots must be populated with `Some` values until
162 /// the first `None` value is encountered, or the end of the array is reached.
163 /// After that, all remaining slots must be `None`.
164 ///
165 /// This is used by the [`re_arr!`] macro.
166 ///
167 /// ## Examples
168 ///
169 /// ```rust
170 /// use combo_vec::{re_arr, ReArr};
171 ///
172 /// let my_re_arr = ReArr::from_arr([Some(1), Some(2), Some(3), None, None]);
173 /// let convenient_re_arr = re_arr![1, 2, 3; None, None];
174 ///
175 /// assert_eq!(my_re_arr, convenient_re_arr);
176 /// assert_eq!(my_re_arr.len(), 3);
177 /// assert_eq!(my_re_arr.capacity(), 5);
178 /// ```
179 #[must_use]
180 #[inline]
181 pub const fn from_arr(arr: [Option<T>; N]) -> Self {
182 let mut arr_len = 0;
183 while arr_len < N && arr[arr_len].is_some() {
184 arr_len += 1;
185 }
186
187 Self { arr, arr_len }
188 }
189
190 // Create a new [`ReArr`] from an iterator reference, taking up to N items
191 //
192 // Allows for initialization without consuming the iterator, leaving its
193 // remaining content for another procedure.
194 //
195 // This is useful for ComboVec::from_iter, which needs to initialise both
196 // a ReArr and a Vec.
197 pub(crate) fn from_iter_ref(iter: &mut impl Iterator<Item = T>) -> Self {
198 let mut re_arr = Self::new();
199 for _ in 0..N {
200 if let Some(val) = iter.next() {
201 re_arr.push(val);
202 continue;
203 }
204 break;
205 }
206 re_arr
207 }
208
209 /// Push an element to the end of the array.
210 ///
211 /// ## Panics
212 ///
213 /// Panics if the array is full.
214 ///
215 /// ## Examples
216 ///
217 /// ```rust
218 /// use combo_vec::{re_arr, ReArr};
219 ///
220 /// let mut my_re_arr = re_arr![1, 2, 3; None];
221 /// my_re_arr.push(4);
222 ///
223 /// assert_eq!(my_re_arr.len(), 4);
224 /// assert_eq!(my_re_arr.capacity(), 4);
225 /// #[cfg(feature = "alloc")]
226 /// assert_eq!(my_re_arr.to_vec(), vec![1, 2, 3, 4]);
227 /// ```
228 #[inline]
229 pub fn push(&mut self, val: T) {
230 self.arr[self.arr_len] = Some(val);
231 self.arr_len += 1;
232 }
233
234 /// Remove the last element from the array and return it, or None if it is empty.
235 ///
236 /// ## Examples
237 ///
238 /// ```rust
239 /// use combo_vec::{re_arr, ReArr};
240 ///
241 /// let mut my_re_arr = re_arr![1, 2, 3; None];
242 ///
243 /// assert_eq!(my_re_arr.pop(), Some(3));
244 /// assert_eq!(my_re_arr.pop(), Some(2));
245 /// assert_eq!(my_re_arr.pop(), Some(1));
246 /// assert_eq!(my_re_arr.pop(), None);
247 /// ```
248 #[inline]
249 pub const fn pop(&mut self) -> Option<T> {
250 if self.is_empty() {
251 None
252 } else {
253 self.arr_len -= 1;
254 self.arr[self.arr_len].take()
255 }
256 }
257
258 /// Get any element from the array as a reference, returning `None` if out of bounds.
259 ///
260 /// ## Examples
261 ///
262 /// ```rust
263 /// use combo_vec::{re_arr, ReArr};
264 ///
265 /// let my_re_arr = re_arr![1, 2, 3; None];
266 ///
267 /// assert_eq!(my_re_arr.get(0), Some(&1));
268 /// assert_eq!(my_re_arr.get(1), Some(&2));
269 /// assert_eq!(my_re_arr.get(2), Some(&3));
270 /// assert_eq!(my_re_arr[2], 3);
271 /// assert_eq!(my_re_arr.get(3), None);
272 /// assert_eq!(my_re_arr.get(4), None);
273 /// assert_eq!(my_re_arr.get(5), None);
274 /// ```
275 #[must_use]
276 #[inline]
277 pub fn get(&self, idx: usize) -> Option<&T> {
278 self.arr.get(idx).and_then(|item| item.as_ref())
279 }
280
281 /// Get any element from the array as a mutable reference, `None` if out of bounds.
282 ///
283 /// ## Examples
284 ///
285 /// ```rust
286 /// use combo_vec::{re_arr, ReArr};
287 ///
288 /// let mut my_re_arr = re_arr![1, 2, 3; None];
289 ///
290 /// assert_eq!(my_re_arr.get_mut(0), Some(&mut 1));
291 /// assert_eq!(my_re_arr.get_mut(1), Some(&mut 2));
292 /// my_re_arr[1] = 4;
293 /// assert_eq!(my_re_arr.get_mut(1), Some(&mut 4));
294 /// assert_eq!(my_re_arr.get_mut(2), Some(&mut 3));
295 /// assert_eq!(my_re_arr.get_mut(3), None);
296 /// assert_eq!(my_re_arr.get_mut(4), None);
297 /// assert_eq!(my_re_arr.get_mut(5), None);
298 /// ```
299 #[must_use]
300 #[inline]
301 pub fn get_mut(&mut self, idx: usize) -> Option<&mut T> {
302 self.arr.get_mut(idx).and_then(|item| item.as_mut())
303 }
304
305 /// How many elements are currently stored.
306 ///
307 /// This is not the same as the capacity of the internal array.
308 ///
309 /// ## Examples
310 ///
311 /// ```rust
312 /// use combo_vec::{re_arr, ReArr};
313 ///
314 /// let mut my_re_arr = re_arr![1, 2, 3; None];
315 ///
316 /// assert_eq!(my_re_arr.len(), 3);
317 /// my_re_arr.push(4);
318 /// assert_eq!(my_re_arr.len(), 4);
319 /// my_re_arr.pop();
320 /// assert_eq!(my_re_arr.len(), 3);
321 /// ```
322 #[inline]
323 pub const fn len(&self) -> usize {
324 self.arr_len
325 }
326
327 /// How many elements can be stored.
328 ///
329 /// ## Examples
330 ///
331 /// ```rust
332 /// use combo_vec::{re_arr, ReArr};
333 ///
334 /// let mut my_re_arr = re_arr![1, 2, 3; None];
335 ///
336 /// assert_eq!(my_re_arr.capacity(), 4);
337 /// my_re_arr.push(4);
338 /// assert_eq!(my_re_arr.capacity(), 4);
339 /// my_re_arr.pop();
340 /// assert_eq!(my_re_arr.capacity(), 4);
341 /// ```
342 #[inline]
343 pub const fn capacity(&self) -> usize {
344 N
345 }
346
347 /// Reduce the number of elements to the given length.
348 ///
349 /// If `new_len` is greater than the current length, this has no effect.
350 ///
351 /// ## Examples
352 ///
353 /// ```rust
354 /// use combo_vec::{re_arr, ReArr};
355 ///
356 /// let mut my_re_arr = re_arr![1, 2, 3; None];
357 ///
358 /// assert_eq!(my_re_arr.len(), 3);
359 /// my_re_arr.truncate(2);
360 /// assert_eq!(my_re_arr.len(), 2);
361 /// ```
362 #[inline]
363 pub fn truncate(&mut self, len: usize) {
364 self.arr[len..].iter_mut().for_each(|x| *x = None);
365 self.arr_len = self.arr_len.min(len);
366 }
367
368 /// Remove all elements from the array.
369 ///
370 /// ## Examples
371 ///
372 /// ```rust
373 /// use combo_vec::{re_arr, ReArr};
374 ///
375 /// let mut my_re_arr = re_arr![1, 2, 3; None];
376 ///
377 /// assert_eq!(my_re_arr.len(), 3);
378 /// my_re_arr.clear();
379 /// assert_eq!(my_re_arr.len(), 0);
380 /// ```
381 #[inline]
382 pub fn clear(&mut self) {
383 self.arr.iter_mut().for_each(|x| *x = None);
384 self.arr_len = 0;
385 }
386
387 /// Removes and returns the element at position with a valid index, shifting all elements after it to the left.
388 ///
389 /// ## Panics
390 ///
391 /// Panics if `index` is out of bounds.
392 ///
393 /// ## Examples
394 ///
395 /// ```rust
396 /// use combo_vec::{re_arr, ReArr};
397 ///
398 /// let mut my_re_arr = re_arr![1, 2, 3; None];
399 ///
400 /// assert_eq!(my_re_arr.remove(1), 2);
401 /// assert_eq!(my_re_arr.len(), 2);
402 /// #[cfg(feature = "alloc")]
403 /// assert_eq!(my_re_arr.to_vec(), vec![1, 3]);
404 /// ```
405 #[inline]
406 pub fn remove(&mut self, index: usize) -> T {
407 let val = self.arr[index].take().unwrap();
408
409 for i in index..self.arr_len - 1 {
410 self.arr[i] = self.arr[i + 1].take();
411 }
412
413 self.arr_len -= 1;
414
415 val
416 }
417
418 /// Removes an element from the `ReArr` and returns it.
419 ///
420 /// The removed element is replaced by the last element of the `ReArr`.
421 ///
422 /// This does not preserve ordering, but is O(1). If you need to preserve the element order, use remove instead.
423 ///
424 /// ## Panics
425 ///
426 /// Panics if `index` is out of bounds, or if it is the last value.
427 ///
428 /// ## Examples
429 ///
430 /// ```rust
431 /// use combo_vec::{re_arr, ReArr};
432 ///
433 /// let mut my_re_arr = re_arr![1, 2, 3; None];
434 ///
435 /// assert_eq!(my_re_arr.swap_remove(0), 1);
436 /// assert_eq!(my_re_arr.len(), 2);
437 /// #[cfg(feature = "alloc")]
438 /// assert_eq!(my_re_arr.to_vec(), vec![3, 2]);
439 /// ```
440 #[inline]
441 pub const fn swap_remove(&mut self, index: usize) -> T {
442 let last_value = self.pop().unwrap();
443 self.arr[index].replace(last_value).unwrap()
444 }
445
446 /// Get the first element, returning `None` if there are no elements.
447 ///
448 /// ## Examples
449 ///
450 /// ```rust
451 /// use combo_vec::{re_arr, ReArr};
452 ///
453 /// let my_re_arr = re_arr![1, 2, 3; None];
454 ///
455 /// assert_eq!(my_re_arr.first(), Some(&1));
456 /// ```
457 #[inline]
458 pub const fn first(&self) -> Option<&T> {
459 if N == 0 {
460 None
461 } else {
462 self.arr[0].as_ref()
463 }
464 }
465
466 /// Get the first element as a mutable reference, returning `None` if there are no elements.
467 ///
468 /// ## Examples
469 ///
470 /// ```rust
471 /// use combo_vec::{re_arr, ReArr};
472 ///
473 /// let mut my_re_arr = re_arr![1, 2, 3; None];
474 ///
475 /// assert_eq!(my_re_arr.first_mut(), Some(&mut 1));
476 /// ```
477 #[inline]
478 pub const fn first_mut(&mut self) -> Option<&mut T> {
479 if N == 0 {
480 None
481 } else {
482 self.arr[0].as_mut()
483 }
484 }
485
486 /// Get the last element, returning `None` if there are no elements.
487 ///
488 /// ## Examples
489 ///
490 /// ```rust
491 /// use combo_vec::{re_arr, ReArr};
492 ///
493 /// let my_re_arr = re_arr![1, 2, 3; None];
494 ///
495 /// assert_eq!(my_re_arr.last(), Some(&3));
496 /// ```
497 #[inline]
498 pub const fn last(&self) -> Option<&T> {
499 if self.is_empty() {
500 None
501 } else {
502 self.arr[self.arr_len - 1].as_ref()
503 }
504 }
505
506 /// Get the last element as a mutable reference, returning `None` if there are no elements.
507 ///
508 /// ## Examples
509 ///
510 /// ```rust
511 /// use combo_vec::{re_arr, ReArr};
512 ///
513 /// let mut my_re_arr = re_arr![1, 2, 3; None];
514 ///
515 /// assert_eq!(my_re_arr.last_mut(), Some(&mut 3));
516 /// ```
517 #[inline]
518 pub const fn last_mut(&mut self) -> Option<&mut T> {
519 if self.is_empty() {
520 None
521 } else {
522 self.arr[self.arr_len - 1].as_mut()
523 }
524 }
525
526 /// Check if there are no elements.
527 ///
528 /// ## Examples
529 ///
530 /// ```rust
531 /// use combo_vec::{re_arr, ReArr};
532 ///
533 /// let my_re_arr = re_arr![1, 2, 3; None];
534 /// assert_eq!(my_re_arr.is_empty(), false);
535 ///
536 /// let empty_re_arr = ReArr::<i32, 3>::new();
537 /// assert_eq!(empty_re_arr.is_empty(), true);
538 /// ```
539 #[inline]
540 pub const fn is_empty(&self) -> bool {
541 self.arr_len == 0
542 }
543
544 /// Get an iterator over the elements of the array.
545 ///
546 /// ## Examples
547 ///
548 /// ```rust
549 /// use combo_vec::{re_arr, ReArr};
550 ///
551 /// let my_re_arr = re_arr![1, 2, 3; None];
552 ///
553 /// assert_eq!(my_re_arr.iter().collect::<Vec<_>>(), vec![&1, &2, &3]);
554 /// ```
555 #[inline]
556 pub fn iter(&self) -> impl Iterator<Item = &T> + '_ {
557 self.arr.iter().flatten()
558 }
559
560 /// Get an iterator over the elements of the array, returning mutable references.
561 ///
562 /// ## Examples
563 ///
564 /// ```rust
565 /// use combo_vec::{re_arr, ReArr};
566 ///
567 /// let mut my_re_arr = re_arr![1, 2, 3; None];
568 ///
569 /// assert_eq!(my_re_arr.iter_mut().collect::<Vec<_>>(), vec![&mut 1, &mut 2, &mut 3]);
570 /// ```
571 #[inline]
572 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> + '_ {
573 self.arr.iter_mut().flatten()
574 }
575
576 /// Extend this array with all the elements from the given iterator.
577 ///
578 /// ## Panics
579 ///
580 /// Panics if the iterator tries to push more elements than the internal array can hold.
581 ///
582 /// ## Examples
583 ///
584 /// ```rust
585 /// use combo_vec::{re_arr, ReArr};
586 ///
587 /// let mut my_re_arr = re_arr![1, 2, 3; None, None, None];
588 /// assert_eq!(my_re_arr.len(), 3);
589 /// assert_eq!(my_re_arr.capacity(), 6);
590 ///
591 /// my_re_arr.extend([4, 5, 6]);
592 /// assert_eq!(my_re_arr.len(), 6);
593 /// ```
594 #[inline]
595 pub fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
596 iter.into_iter().for_each(|x| self.push(x));
597 }
598
599 /// Get this [`ReArr`] transformed into a [`Vec`].
600 ///
601 /// ## Examples
602 ///
603 /// ```rust
604 /// use combo_vec::{re_arr, ReArr};
605 ///
606 /// let my_re_arr = re_arr![1, 2, 3; None];
607 ///
608 /// assert_eq!(my_re_arr.into_vec(), vec![1, 2, 3]);
609 /// ```
610 #[cfg(feature = "alloc")]
611 #[inline]
612 pub fn into_vec(self) -> Vec<T> {
613 self.into_iter().collect()
614 }
615
616 /// Get this [`ReArr`] represented as a [`Vec`], borrowing data instead of moving it.
617 ///
618 /// ## Examples
619 ///
620 /// ```rust
621 /// use combo_vec::{re_arr, ReArr};
622 ///
623 /// let my_re_arr = re_arr![1, 2, 3; None];
624 ///
625 /// assert_eq!(my_re_arr.ref_vec(), vec![&1, &2, &3]);
626 /// ```
627 #[cfg(feature = "alloc")]
628 #[inline]
629 pub fn ref_vec(&self) -> Vec<&T> {
630 self.iter().collect()
631 }
632}
633
634impl<T: Clone, const N: usize> ReArr<T, N> {
635 /// Get this [`ReArr`] represented as a [`Vec`].
636 ///
637 /// ## Examples
638 ///
639 /// ```rust
640 /// use combo_vec::{re_arr, ReArr};
641 ///
642 /// let my_re_arr = re_arr![1, 2, 3; None];
643 ///
644 /// assert_eq!(my_re_arr.to_vec(), vec![1, 2, 3]);
645 /// // my_re_arr is still usable
646 /// assert_eq!(my_re_arr.len(), 3);
647 /// ```
648 #[cfg(feature = "alloc")]
649 #[inline]
650 pub fn to_vec(&self) -> Vec<T> {
651 self.iter().cloned().collect()
652 }
653
654 /// Resizes the [`ReArr`] in-place so that `len` is equal to `new_len`.
655 ///
656 /// If `new_len` is greater than `len`, the [`ReArr`] is extended by the
657 /// difference, with each additional slot filled with `val`.
658 ///
659 /// If `new_len` is less than `len`, the [`ReArr`] is truncated.
660 ///
661 /// ## Panics
662 ///
663 /// If `new_len` is greater than the length of the internal array.
664 ///
665 /// # Examples
666 ///
667 /// ```rust
668 /// use combo_vec::{re_arr, ReArr};
669 ///
670 /// let mut my_re_arr = re_arr![1, 2, 3; None, None];
671 ///
672 /// assert_eq!(my_re_arr.len(), 3);
673 /// my_re_arr.resize(5, 4);
674 /// assert_eq!(my_re_arr.len(), 5);
675 /// #[cfg(feature = "alloc")]
676 /// assert_eq!(my_re_arr.to_vec(), vec![1, 2, 3, 4, 4]);
677 /// my_re_arr.resize(2, 4);
678 /// assert_eq!(my_re_arr.len(), 2);
679 /// #[cfg(feature = "alloc")]
680 /// assert_eq!(my_re_arr.to_vec(), vec![1, 2]);
681 /// ```
682 pub fn resize(&mut self, new_len: usize, val: T) {
683 assert!(
684 new_len <= N,
685 "new length cannot be greater than the internal array length"
686 );
687
688 if new_len > self.arr_len {
689 self.arr[self.arr_len..new_len].fill(Some(val));
690 } else {
691 self.arr[new_len..].fill(None);
692 }
693
694 self.arr_len = new_len;
695 }
696
697 /// Resizes the [`ReArr`] in-place so that `len` is equal to `new_len`.
698 ///
699 /// If `new_len` is greater than `len`, the [`ReArr`] is extended
700 /// with the result of calling the closure `f`.
701 ///
702 /// If `new_len` is less than `len`, the [`ReArr`] is truncated.
703 ///
704 /// ## Panics
705 ///
706 /// If `new_len` is greater than the length of the internal array.
707 ///
708 /// # Examples
709 ///
710 /// ```rust
711 /// use combo_vec::{re_arr, ReArr};
712 ///
713 /// let mut my_re_arr = re_arr![1, 2, 3; None, None];
714 ///
715 /// assert_eq!(my_re_arr.len(), 3);
716 /// my_re_arr.resize_with(5, Default::default);
717 /// assert_eq!(my_re_arr.len(), 5);
718 /// #[cfg(feature = "alloc")]
719 /// assert_eq!(my_re_arr.to_vec(), vec![1, 2, 3, 0, 0]);
720 /// my_re_arr.resize_with(2, Default::default);
721 /// assert_eq!(my_re_arr.len(), 2);
722 /// #[cfg(feature = "alloc")]
723 /// assert_eq!(my_re_arr.to_vec(), vec![1, 2]);
724 /// ```
725 pub fn resize_with<F: FnMut() -> T>(&mut self, new_len: usize, mut f: F) {
726 assert!(
727 new_len <= N,
728 "new length cannot be greater than the internal array length"
729 );
730
731 if new_len > self.arr_len {
732 self.arr[self.arr_len..new_len].fill(Some(f()));
733 } else {
734 self.arr[new_len..].fill(None);
735 }
736
737 self.arr_len = new_len;
738 }
739}
740
741#[cfg(feature = "alloc")]
742impl<T: ToString, const N: usize> ReArr<T, N> {
743 /// Joins the [`ReArr`] into a string with a separator.
744 ///
745 /// ## Examples
746 ///
747 /// ```rust
748 /// use combo_vec::re_arr;
749 ///
750 /// let x = re_arr![1, 2, 3];
751 /// assert_eq!(x.join(", "), "1, 2, 3");
752 /// ```
753 pub fn join(&self, sep: &str) -> String {
754 self.iter()
755 .enumerate()
756 .fold(String::with_capacity(self.arr_len), |mut s, (i, item)| {
757 if i != 0 {
758 s.push_str(sep);
759 }
760
761 s.push_str(&item.to_string());
762 s
763 })
764 }
765}
766
767impl<T, const N: usize> ops::Index<usize> for ReArr<T, N> {
768 type Output = T;
769
770 #[inline]
771 fn index(&self, idx: usize) -> &Self::Output {
772 self.arr[idx].as_ref().unwrap()
773 }
774}
775
776impl<T, const N: usize> ops::IndexMut<usize> for ReArr<T, N> {
777 #[inline]
778 fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
779 self.arr[idx].as_mut().unwrap()
780 }
781}
782
783impl<T, const N: usize> IntoIterator for ReArr<T, N> {
784 type Item = T;
785 type IntoIter = Flatten<ArrayIter<Option<T>, N>>;
786
787 #[inline]
788 fn into_iter(self) -> Self::IntoIter {
789 self.arr.into_iter().flatten()
790 }
791}
792
793impl<T, const N: usize> FromIterator<T> for ReArr<T, N> {
794 #[inline]
795 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
796 Self::from_iter_ref(&mut iter.into_iter())
797 }
798}
799
800impl<T: Debug, const N: usize> Debug for ReArr<T, N> {
801 #[inline]
802 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
803 f.debug_struct("ReArr")
804 .field("arr", &self.arr)
805 .field("arr_len", &self.arr_len)
806 .finish()
807 }
808}
809
810impl<T: Debug, const N: usize> Display for ReArr<T, N> {
811 #[inline]
812 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
813 f.debug_list().entries(self.arr.iter().flatten()).finish()
814 }
815}