utils/
array.rs

1//! Array helpers.
2
3use std::fmt;
4use std::hash::Hash;
5use std::ops::{Deref, DerefMut};
6
7/// A fixed-size array-backed vector.
8///
9/// `ArrayVec` has a fixed-sized `N` long array and a length field to track how many elements are
10/// populated. It is useful for storing a small but variable number of elements without heap
11/// allocation.
12///
13/// The implementation is intentionally simple, and requires [`Copy`] and [`Default`] bounds on some
14/// methods instead of using [`std::mem::MaybeUninit`].
15#[derive(Clone, PartialEq, Eq, Hash)]
16pub struct ArrayVec<T, const N: usize> {
17    len: usize,
18    data: [T; N],
19}
20
21impl<T, const N: usize> ArrayVec<T, N> {
22    /// Creates a new empty `ArrayVec`.
23    ///
24    /// # Examples
25    /// ```
26    /// # use utils::array::ArrayVec;
27    /// let vec: ArrayVec<i32, 5> = ArrayVec::new();
28    /// assert_eq!(vec.len(), 0);
29    /// ```
30    #[inline]
31    #[must_use]
32    pub fn new() -> Self
33    where
34        T: Copy + Default,
35    {
36        Self {
37            len: 0,
38            data: [T::default(); N],
39        }
40    }
41
42    /// Adds an element to the end of the vector.
43    ///
44    /// Returns [`Err`] containing the provided value if the vector is already full.
45    ///
46    /// # Examples
47    /// ```
48    /// # use utils::array::ArrayVec;
49    /// let mut vec: ArrayVec<i32, 2> = ArrayVec::new();
50    /// assert_eq!(vec.push(1), Ok(()));
51    /// assert_eq!(vec.push(2), Ok(()));
52    /// assert_eq!(vec.push(3), Err(3)); // Vector is full
53    /// ```
54    #[inline]
55    pub fn push(&mut self, value: T) -> Result<(), T> {
56        if self.len < N {
57            self.data[self.len] = value;
58            self.len += 1;
59            Ok(())
60        } else {
61            Err(value)
62        }
63    }
64
65    /// Removes the last element from the vector and returns it, or [`None`] if it is empty.
66    ///
67    /// # Examples
68    /// ```
69    /// # use utils::array::ArrayVec;
70    /// let mut vec: ArrayVec<i32, 3> = ArrayVec::new();
71    /// vec.push(1).unwrap();
72    /// assert_eq!(vec.pop(), Some(1));
73    /// assert_eq!(vec.pop(), None);
74    /// ```
75    #[inline]
76    pub fn pop(&mut self) -> Option<T>
77    where
78        T: Default,
79    {
80        if self.len > 0 {
81            self.len -= 1;
82            Some(std::mem::take(&mut self.data[self.len]))
83        } else {
84            None
85        }
86    }
87
88    /// Returns a slice of all the populated elements in the vector.
89    ///
90    /// # Examples
91    ///
92    /// ```
93    /// # use utils::array::ArrayVec;
94    /// let mut vec: ArrayVec<i32, 3> = ArrayVec::new();
95    /// vec.push(1).unwrap();
96    /// vec.push(2).unwrap();
97    /// assert_eq!(vec.as_slice(), &[1, 2]);
98    /// ```
99    #[inline]
100    pub fn as_slice(&self) -> &[T] {
101        #[cfg(feature = "unsafe")]
102        unsafe {
103            std::hint::assert_unchecked(self.len <= N);
104        }
105
106        &self.data[..self.len]
107    }
108
109    /// Returns a mutable slice of all the populated elements in the vector.
110    ///
111    /// # Examples
112    ///
113    /// ```
114    /// # use utils::array::ArrayVec;
115    /// let mut vec: ArrayVec<i32, 3> = ArrayVec::new();
116    /// vec.push(1).unwrap();
117    /// vec.push(2).unwrap();
118    /// let mut slice = vec.as_mut_slice();
119    /// slice[1] = 10;
120    /// assert_eq!(slice, &[1, 10]);
121    /// ```
122    #[inline]
123    pub fn as_mut_slice(&mut self) -> &mut [T] {
124        #[cfg(feature = "unsafe")]
125        unsafe {
126            std::hint::assert_unchecked(self.len <= N);
127        }
128
129        &mut self.data[..self.len]
130    }
131
132    /// Returns the capacity of the vector, which is always `N`.
133    ///
134    /// # Examples
135    /// ```
136    /// # use utils::array::ArrayVec;
137    /// let vec: ArrayVec<i32, 5> = ArrayVec::new();
138    /// assert_eq!(vec.capacity(), 5);
139    /// ```
140    #[inline]
141    pub fn capacity(&self) -> usize {
142        N
143    }
144
145    /// Returns whether the vector is full.
146    ///
147    /// # Examples
148    ///
149    /// ```
150    /// # use utils::array::ArrayVec;
151    /// let mut vec: ArrayVec<i32, 2> = ArrayVec::new();
152    /// assert!(!vec.is_full());
153    /// vec.push(1).unwrap();
154    /// assert!(!vec.is_full());
155    /// vec.push(2).unwrap();
156    /// assert!(vec.is_full());
157    /// ```
158    #[inline]
159    pub fn is_full(&self) -> bool {
160        self.len == N
161    }
162}
163
164impl<T, const N: usize> Deref for ArrayVec<T, N> {
165    type Target = [T];
166
167    #[inline]
168    fn deref(&self) -> &Self::Target {
169        self.as_slice()
170    }
171}
172
173impl<T, const N: usize> DerefMut for ArrayVec<T, N> {
174    #[inline]
175    fn deref_mut(&mut self) -> &mut Self::Target {
176        self.as_mut_slice()
177    }
178}
179
180impl<'a, T, const N: usize> IntoIterator for &'a ArrayVec<T, N> {
181    type Item = &'a T;
182    type IntoIter = std::slice::Iter<'a, T>;
183
184    #[inline]
185    fn into_iter(self) -> Self::IntoIter {
186        self.iter()
187    }
188}
189
190impl<'a, T, const N: usize> IntoIterator for &'a mut ArrayVec<T, N> {
191    type Item = &'a mut T;
192    type IntoIter = std::slice::IterMut<'a, T>;
193
194    #[inline]
195    fn into_iter(self) -> Self::IntoIter {
196        self.iter_mut()
197    }
198}
199
200impl<T: fmt::Debug, const N: usize> fmt::Debug for ArrayVec<T, N> {
201    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
202        f.debug_struct("ArrayVec")
203            .field("len", &self.len)
204            .field("cap", &N)
205            .field("data", &self.as_slice())
206            .finish()
207    }
208}
209
210impl<T: Default + Copy, const N: usize> Default for ArrayVec<T, N> {
211    fn default() -> Self {
212        Self::new()
213    }
214}