stack_vector/lib.rs
1//! A vector-like object allocated on the stack
2//!
3//! # Example
4//! ```
5//! use stack_vector::StackVec;
6//!
7//! let mut sv = StackVec::<i32, 10>::new();
8//!
9//! sv.push(1);
10//!
11//! if false {
12//! sv.push(2);
13//! }
14//!
15//! sv.push(3);
16//!
17//! if true {
18//! sv.push(4);
19//! }
20//!
21//! assert_eq!(sv.as_slice(), &[1, 3, 4]);
22//! ```
23
24#![no_std]
25
26use core::iter::Peekable;
27use core::mem::{self, ManuallyDrop, MaybeUninit};
28use core::ops::{Deref, DerefMut};
29use core::ptr;
30
31/// A [Vec]-like wrapper for an array.
32///
33/// This struct allows to push and pop to an array,
34/// treating it like a vector, but with no heap allocations.
35#[derive(Debug)]
36pub struct StackVec<T, const CAP: usize> {
37 inner: [MaybeUninit<T>; CAP],
38 length: usize,
39}
40
41impl<T, const CAP: usize> StackVec<T, CAP> {
42
43 /// Creates a new empty StackVec
44 #[inline]
45 pub const fn new() -> Self {
46 Self {
47 inner: [const { MaybeUninit::uninit() }; CAP ],
48 length: 0
49 }
50 }
51
52 /// Creates a new StackVec, filled with copies of the given value
53 ///
54 /// # Example
55 /// ```
56 /// use stack_vector::StackVec;
57 ///
58 /// let v = StackVec::<i32, 5>::filled(0);
59 /// assert_eq!(v.as_slice(), &[0, 0, 0, 0, 0]);
60 /// ```
61 #[inline(always)]
62 pub fn filled(val: T) -> Self
63 where
64 T: Clone
65 {
66 Self::generate(|| val.clone())
67 }
68
69 /// Creates a new StackVec, filling it using the given generator function
70 ///
71 /// # Example
72 /// ```
73 /// use stack_vector::StackVec;
74 ///
75 /// let mut n = 0;
76 /// let v = StackVec::<i32, 5>::generate(|| {
77 /// n += 1;
78 /// n
79 /// });
80 ///
81 /// assert_eq!(v.len(), 5);
82 /// assert_eq!(v.as_slice(), &[1, 2, 3, 4, 5]);
83 /// ```
84 pub fn generate<Gen>(mut generator: Gen) -> Self
85 where
86 Gen: FnMut() -> T
87 {
88 let mut s = Self::new();
89 for _ in 0..CAP {
90 unsafe {
91 /* SAFETY: We only call this function CAP
92 * times, so it's never gonna fail */
93 s.push_unchecked(generator());
94 }
95 }
96 s
97 }
98
99 /// Creates a new StackVec from the given array of T
100 ///
101 /// # Example
102 /// ```
103 /// use stack_vector::StackVec;
104 ///
105 /// let v = StackVec::from_array([1, 2, 3, 4, 5]);
106 ///
107 /// assert_eq!(v.len(), 5);
108 /// assert_eq!(v.as_slice(), &[1, 2, 3, 4, 5]);
109 /// ```
110 pub const fn from_array(arr: [T; CAP]) -> Self {
111 /* We can't transmute the array due to rust's limitations.
112 * We need to wrap the array into a ManuallyDrop, to avoid
113 * T's Drop to be called twice. */
114 let arr = ManuallyDrop::new(arr);
115 let inner = unsafe {
116 /* SAFETY: T and ManualyDrop<T> have the same size and alignment */
117 mem::transmute_copy(&arr)
118 };
119 Self { inner, length: CAP }
120 }
121
122 /// Pushes an element in the StackVec without checking bounds.
123 ///
124 /// # Safety
125 /// Caller must ensure that the StackVec has room for the element
126 #[inline]
127 pub unsafe fn push_unchecked(&mut self, val: T) {
128 unsafe {
129 self.as_mut_ptr().add(self.length).write(val);
130 }
131 self.length += 1;
132 }
133
134 /// Pushes an element into this StackVec, panicking if there is no space left.
135 ///
136 /// # Panics
137 /// - If the StackVec is full
138 #[inline]
139 pub fn push(&mut self, val: T) {
140 if self.try_push(val).is_err() {
141 panic!("Attemp to push beyond the capacity of the array")
142 }
143 }
144
145 /// Attempts to push an element into this StackVec.
146 ///
147 /// # Errors
148 /// - If the StackVec if full, returns back the element
149 /// inside an Err variant.
150 pub fn try_push(&mut self, val: T) -> Result<(),T> {
151 if self.length >= CAP {
152 Err(val)
153 } else {
154 /* SAFETY: We've just checked that the buffer can
155 * hold the element */
156 unsafe { self.push_unchecked(val) };
157 Ok(())
158 }
159 }
160
161 /// Pushes all the elements from the iterator into this StackVec.
162 #[inline]
163 pub fn extend_from_iter<I>(&mut self, it: I)
164 where
165 I: IntoIterator<Item = T>
166 {
167 for elem in it.into_iter() {
168 self.push(elem)
169 }
170 }
171
172 /// Attempts to push all the elements from the iterator into this StackVec.
173 ///
174 /// # Errors
175 /// If the iterator yields more elements that we can push, returns the
176 /// iterator (turned into a [Peekable]) as an Err variant
177 pub fn try_extend_from_iter<I>(&mut self, it: I) -> Result<(), Peekable<<I as IntoIterator>::IntoIter>>
178 where
179 I: IntoIterator<Item = T>
180 {
181 let mut it = it.into_iter().peekable();
182 while it.peek().is_some() {
183 if self.length >= CAP {
184 return Err(it)
185 }
186 unsafe {
187 /* SAFETY:
188 * 1) In the while condition, we've checked that the
189 * iterator has a next element.
190 *
191 * 2) In the condition above, we check that there's room
192 * for this element
193 * */
194 let elem = it.next().unwrap_unchecked();
195 self.push_unchecked(elem)
196 }
197 }
198 Ok(())
199 }
200
201 /// Removes the ith element of the StackVec, and returns it.
202 ///
203 /// # Safety
204 /// - i must be within bounds [0, [Self::len])
205 pub unsafe fn remove_unchecked(&mut self, i: usize) -> T {
206 /* SAFETY: self.inner[i] is initialized, thus reading
207 * from this pointer is safe */
208 let ret = unsafe { self.inner[i].assume_init_read() };
209
210 let ptr = self.inner.as_mut_ptr();
211
212 unsafe {
213 /* SAFETY: Elements [i + 1, len) are within bounds
214 * for the buffer, and can be copied over */
215 ptr::copy(
216 ptr.add(i + 1),
217 ptr.add(i),
218 self.length - i - 1
219 );
220 }
221 self.length -= 1;
222 ret
223 }
224
225 /// Removes the ith element of the StackVec, and returns it.
226 /// If the index is out of bounds, returns None
227 pub fn remove(&mut self, i: usize) -> Option<T> {
228 if i <= self.length {
229 unsafe { Some(self.remove_unchecked(i)) }
230 } else {
231 None
232 }
233 }
234
235 /// Removes the last element of the StackVec, and returns it.
236 /// If empty, returns None
237 #[inline(always)]
238 pub fn pop(&mut self) -> Option<T> {
239 self.remove(self.length)
240 }
241
242 /// Returns an slice of T's from this StackVec, with all
243 /// the currently allocated elements.
244 pub const fn as_slice(&self) -> &[T] {
245 let (slice, _) = self.inner.split_at(self.length);
246 /* SAFETY: The items in range 0..self.len will allways be
247 * initialized, so it's safe to reinterpret the slice of
248 * MaybeUninit to an slice of T */
249 unsafe {
250 mem::transmute::<&[MaybeUninit<T>], &[T]>(slice)
251 }
252 }
253
254 /// Returns a mutable slice of T's from this StackVec, with
255 /// all the currently allocated elements.
256 pub const fn as_slice_mut(&mut self) -> &mut [T] {
257 let (slice, _) = self.inner.split_at_mut(self.length);
258 /* SAFETY: Same as as_slice */
259 unsafe {
260 mem::transmute::<&mut [MaybeUninit<T>], &mut [T]>(slice)
261 }
262 }
263
264 /// Returns this StackVec's buffer as a *const T.
265 #[inline(always)]
266 pub const fn as_ptr(&self) -> *const T {
267 self.inner.as_ptr() as *const T
268 }
269
270 /// Returns this StackVec's buffer as a *mut T.
271 #[inline(always)]
272 pub const fn as_mut_ptr(&mut self) -> *mut T {
273 self.inner.as_mut_ptr() as *mut T
274 }
275
276 /// Returns the capacity of this StackVec.
277 /// This is just a convenience function, since the
278 /// capacity is a const generic argument.
279 #[inline(always)]
280 pub const fn capacity(&self) -> usize { CAP }
281
282 /// Returns the remaining capacity of this StackVec.
283 /// This is, how many more elements can we store in it.
284 #[inline(always)]
285 pub const fn remaining_capacity(&self) -> usize { CAP - self.length }
286
287 /// Returns the length of this StackVec, this is, the
288 /// number of elements "pushed" into it.
289 #[inline(always)]
290 pub const fn len(&self) -> usize { self.length }
291
292 /// Returns true if the length is 0
293 #[inline(always)]
294 pub const fn is_empty(&self) -> bool { self.length == 0 }
295
296 /// Returns true if no more elements can be pushed into this StackVec
297 #[inline(always)]
298 pub const fn is_full(&self) -> bool { self.length == CAP }
299}
300
301impl<T, const CAP: usize> Deref for StackVec<T, CAP> {
302 type Target = [T];
303
304 #[inline(always)]
305 fn deref(&self) -> &Self::Target {
306 self.as_slice()
307 }
308}
309
310impl<T, const CAP: usize> DerefMut for StackVec<T, CAP> {
311 #[inline(always)]
312 fn deref_mut(&mut self) -> &mut [T] {
313 self.as_slice_mut()
314 }
315}
316
317impl<T, const CAP: usize> Default for StackVec<T, CAP> {
318 #[inline(always)]
319 fn default() -> Self {
320 Self::new()
321 }
322}
323
324impl<T, const CAP: usize> From<[T; CAP]> for StackVec<T, CAP> {
325 #[inline(always)]
326 fn from(value: [T; CAP]) -> Self {
327 StackVec::from_array(value)
328 }
329}
330
331impl<T, const CAP: usize> Drop for StackVec<T, CAP> {
332 fn drop(&mut self) {
333 if mem::needs_drop::<T>() {
334 for elem in &mut self.inner[0..self.length] {
335 unsafe {
336 /* SAFETY: Elements [0, len) are initialized, and
337 * must be dropped */
338 elem.assume_init_drop();
339 }
340 }
341 }
342 }
343}
344
345impl<T: Clone, const CAP: usize> Clone for StackVec<T, CAP> {
346 fn clone(&self) -> Self {
347 let mut inner = [const { MaybeUninit::uninit() }; CAP];
348 let src = self.inner.as_ptr();
349 let dst = inner.as_mut_ptr();
350 unsafe { ptr::copy(src, dst, self.length); }
351 Self {
352 inner,
353 length: self.length,
354 }
355 }
356}
357
358impl<T: PartialEq, const CAP: usize> PartialEq for StackVec<T, CAP> {
359 fn eq(&self, other: &Self) -> bool {
360 self.as_slice().iter().eq(other.as_slice().iter())
361 }
362}
363
364impl<T: PartialOrd, const CAP: usize> PartialOrd for StackVec<T, CAP> {
365 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
366 self.as_slice().iter().partial_cmp(other.as_slice().iter())
367 }
368}