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}