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 /// Returns the backing array.
164 ///
165 /// Any items after the current length will be set to the default value.
166 ///
167 /// # Examples
168 /// ```
169 /// # use utils::array::ArrayVec;
170 /// let mut vec: ArrayVec<i32, 5> = ArrayVec::new();
171 /// vec.push(1).unwrap();
172 /// vec.push(2).unwrap();
173 /// vec.push(3).unwrap();
174 /// vec.pop().unwrap();
175 /// assert_eq!(vec.into_array(), [1, 2, 0, 0, 0]);
176 /// ```
177 #[inline]
178 pub fn into_array(self) -> [T; N] {
179 self.data
180 }
181}
182
183impl<T, const N: usize> Deref for ArrayVec<T, N> {
184 type Target = [T];
185
186 #[inline]
187 fn deref(&self) -> &Self::Target {
188 self.as_slice()
189 }
190}
191
192impl<T, const N: usize> DerefMut for ArrayVec<T, N> {
193 #[inline]
194 fn deref_mut(&mut self) -> &mut Self::Target {
195 self.as_mut_slice()
196 }
197}
198
199impl<'a, T, const N: usize> IntoIterator for &'a ArrayVec<T, N> {
200 type Item = &'a T;
201 type IntoIter = std::slice::Iter<'a, T>;
202
203 #[inline]
204 fn into_iter(self) -> Self::IntoIter {
205 self.iter()
206 }
207}
208
209impl<'a, T, const N: usize> IntoIterator for &'a mut ArrayVec<T, N> {
210 type Item = &'a mut T;
211 type IntoIter = std::slice::IterMut<'a, T>;
212
213 #[inline]
214 fn into_iter(self) -> Self::IntoIter {
215 self.iter_mut()
216 }
217}
218
219impl<T: fmt::Debug, const N: usize> fmt::Debug for ArrayVec<T, N> {
220 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
221 f.debug_struct("ArrayVec")
222 .field("len", &self.len)
223 .field("cap", &N)
224 .field("data", &self.as_slice())
225 .finish()
226 }
227}
228
229impl<T: Default + Copy, const N: usize> Default for ArrayVec<T, N> {
230 fn default() -> Self {
231 Self::new()
232 }
233}