Skip to main content

sigma_bounded/
vec.rs

1//! Defines [`Vec`] and associated types.
2
3#[cfg(feature = "alloc")]
4extern crate alloc;
5
6use core::{hash, iter::FromIterator, slice};
7
8use crate::error::{Error, Result};
9
10#[cfg(feature = "alloc")]
11type Inner<T, const N: usize> = alloc::vec::Vec<T>;
12#[cfg(not(feature = "alloc"))]
13type Inner<T, const N: usize> = heapless::Vec<T, N>;
14
15/// A contiguous growable array type.
16///
17/// When `heapless` feature is enabled, this is wrapper around `heapless::Vec`. Otherwise, this is
18/// a wrapper around `alloc::vec::Vec`, sized so logical length never exceeds `N`.
19///
20/// For [`FromIterator`], iteration stops at `N` elements; yielding more panics with the same message
21/// as `heapless::Vec` (`"Vec::from_iter overflow"`).
22#[derive(Clone, Debug)]
23pub struct Vec<T, const N: usize>(Inner<T, N>);
24
25impl<T, const N: usize> Vec<T, N> {
26    /// Constructs a new, empty vector with a capacity of `N`.
27    #[inline]
28    pub fn new() -> Self {
29        Self::default()
30    }
31
32    /// Constructs a new vector with a capacity of `N` and fills it with the provided slice.
33    #[inline]
34    pub fn from_slice(other: &[T]) -> Result<Self>
35    where
36        T: Clone,
37    {
38        #[cfg(feature = "alloc")]
39        {
40            if other.len() > N {
41                return Err(Error::CapacityExceeded);
42            }
43            let mut v = Self(Inner::with_capacity(other.len()));
44            v.0.extend_from_slice(other);
45            Ok(v)
46        }
47        #[cfg(not(feature = "alloc"))]
48        {
49            let mut v = Self::new();
50            v.extend_from_slice(other)?;
51            Ok(v)
52        }
53    }
54
55    /// Extracts a slice containing the entire vector.
56    #[inline]
57    pub fn as_slice(&self) -> &[T] {
58        &self.0
59    }
60
61    /// Extracts a mutable slice containing the entire vector.
62    #[inline]
63    pub fn as_mut_slice(&mut self) -> &mut [T] {
64        &mut self.0
65    }
66
67    /// Returns the length of the vector.
68    #[inline]
69    pub fn len(&self) -> usize {
70        self.0.len()
71    }
72
73    /// Returns `true` if the vector contains no elements.
74    #[inline]
75    pub fn is_empty(&self) -> bool {
76        self.0.is_empty()
77    }
78
79    /// Clears the vector, removing all values.
80    #[inline]
81    pub fn clear(&mut self) {
82        self.0.clear();
83    }
84
85    /// Clones and appends all elements in a slice to the `Vec`.
86    #[inline]
87    pub fn extend_from_slice(&mut self, other: &[T]) -> Result<()>
88    where
89        T: Clone,
90    {
91        #[cfg(feature = "alloc")]
92        {
93            let current_len = self.0.len();
94            let new_len = current_len.saturating_add(other.len());
95            if new_len > N {
96                return Err(Error::CapacityExceeded);
97            }
98            let current_cap = self.0.capacity();
99            if current_cap < new_len {
100                self.0.reserve_exact(new_len - current_cap);
101            }
102            self.0.extend_from_slice(other);
103            Ok(())
104        }
105        #[cfg(not(feature = "alloc"))]
106        {
107            self.0
108                .extend_from_slice(other)
109                .map_err(|_| Error::CapacityExceeded)
110        }
111    }
112
113    /// Appends an `item` to the back of the collection.
114    #[inline]
115    pub fn push(&mut self, item: T) -> Result<()> {
116        #[cfg(feature = "alloc")]
117        {
118            if self.0.len() >= N {
119                return Err(Error::CapacityExceeded);
120            }
121            self.0.push(item);
122            Ok(())
123        }
124        #[cfg(not(feature = "alloc"))]
125        {
126            self.0.push(item).map_err(|_| Error::CapacityExceeded)
127        }
128    }
129
130    /// Returns a reference to an element or subslice, without doing bounds checking.
131    #[inline]
132    pub fn get(&self, index: usize) -> Option<&T> {
133        self.0.get(index)
134    }
135
136    /// Returns an iterator over the slice.
137    #[inline]
138    pub fn iter(&self) -> slice::Iter<'_, T> {
139        self.0.iter()
140    }
141
142    /// Returns a mutable iterator over the slice.
143    #[inline]
144    pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> {
145        self.0.iter_mut()
146    }
147
148    /// Consumes the Vec and returns the inner representation.
149    #[inline]
150    #[cfg(not(feature = "alloc"))]
151    pub(crate) fn into_inner(self) -> Inner<T, N> {
152        self.0
153    }
154}
155
156impl<'a, T, const N: usize> IntoIterator for &'a Vec<T, N> {
157    type Item = &'a T;
158    type IntoIter = slice::Iter<'a, T>;
159
160    #[inline]
161    fn into_iter(self) -> Self::IntoIter {
162        self.iter()
163    }
164}
165
166#[cfg(feature = "alloc")]
167impl<T, const N: usize> IntoIterator for Vec<T, N> {
168    type Item = T;
169    type IntoIter = alloc::vec::IntoIter<T>;
170
171    #[inline]
172    fn into_iter(self) -> Self::IntoIter {
173        self.0.into_iter()
174    }
175}
176
177#[cfg(not(feature = "alloc"))]
178impl<T, const N: usize> IntoIterator for Vec<T, N> {
179    type Item = T;
180    type IntoIter = heapless::vec::IntoIter<T, N, usize>;
181
182    #[inline]
183    fn into_iter(self) -> Self::IntoIter {
184        self.0.into_iter()
185    }
186}
187
188impl<T, const N: usize> FromIterator<T> for Vec<T, N> {
189    fn from_iter<I>(iter: I) -> Self
190    where
191        I: IntoIterator<Item = T>,
192    {
193        #[cfg(feature = "alloc")]
194        {
195            let iter = iter.into_iter();
196            let (lower, upper) = iter.size_hint();
197            let reserve = upper.unwrap_or(lower).min(N);
198            let mut v = alloc::vec::Vec::new();
199            if reserve > 0 {
200                v.reserve_exact(reserve);
201            }
202            for item in iter {
203                if v.len() >= N {
204                    panic!("Vec::from_iter overflow");
205                }
206                v.push(item);
207            }
208            Self(v)
209        }
210        #[cfg(not(feature = "alloc"))]
211        {
212            Self(Inner::from_iter(iter))
213        }
214    }
215}
216
217impl<T, const N: usize> hash::Hash for Vec<T, N>
218where
219    T: hash::Hash,
220{
221    #[inline]
222    fn hash<H: hash::Hasher>(&self, state: &mut H) {
223        self.0.hash(state);
224    }
225}
226
227impl<T, const N: usize> PartialEq for Vec<T, N>
228where
229    T: PartialEq,
230{
231    #[inline]
232    fn eq(&self, other: &Self) -> bool {
233        self.0 == other.0
234    }
235}
236
237impl<T, const N: usize> Eq for Vec<T, N> where T: Eq {}
238
239impl<T, const N: usize> Default for Vec<T, N> {
240    #[inline]
241    fn default() -> Self {
242        #[cfg(feature = "alloc")]
243        {
244            Self(Inner::with_capacity(N))
245        }
246        #[cfg(not(feature = "alloc"))]
247        {
248            Self(Inner::new())
249        }
250    }
251}
252
253impl<T, const N: usize> core::ops::Index<usize> for Vec<T, N> {
254    type Output = T;
255
256    #[inline]
257    fn index(&self, index: usize) -> &Self::Output {
258        &self.0[index]
259    }
260}
261
262impl<T, const N: usize> core::ops::Deref for Vec<T, N> {
263    type Target = [T];
264
265    #[inline]
266    fn deref(&self) -> &Self::Target {
267        self.as_slice()
268    }
269}
270
271#[cfg(all(test, feature = "alloc"))]
272mod from_iter_tests {
273    use super::Vec;
274
275    #[test]
276    fn from_iter_collects_up_to_n() {
277        let v: Vec<u8, 4> = [1, 2, 3, 4].into_iter().collect();
278        assert_eq!(v.as_slice(), [1, 2, 3, 4]);
279    }
280
281    #[test]
282    #[should_panic(expected = "Vec::from_iter overflow")]
283    fn from_iter_panics_when_more_than_n() {
284        let _: Vec<u8, 2> = [1_u8, 2, 3].into_iter().collect();
285    }
286
287    #[test]
288    #[should_panic(expected = "Vec::from_iter overflow")]
289    fn from_iter_panics_despite_lying_upper_hint() {
290        struct BadHint<I>(I);
291        impl<I: Iterator<Item = u8>> Iterator for BadHint<I> {
292            type Item = u8;
293            fn next(&mut self) -> Option<Self::Item> {
294                self.0.next()
295            }
296            fn size_hint(&self) -> (usize, Option<usize>) {
297                (0, Some(1))
298            }
299        }
300        let _: Vec<u8, 2> = BadHint([1_u8, 2, 3].into_iter()).collect();
301    }
302}