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}