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.extend_from_slice(other).map_err(|_| Error::CapacityExceeded)
108        }
109    }
110
111    /// Appends an `item` to the back of the collection.
112    #[inline]
113    pub fn push(&mut self, item: T) -> Result<()> {
114        #[cfg(feature = "alloc")]
115        {
116            if self.0.len() >= N {
117                return Err(Error::CapacityExceeded);
118            }
119            self.0.push(item);
120            Ok(())
121        }
122        #[cfg(not(feature = "alloc"))]
123        {
124            self.0.push(item).map_err(|_| Error::CapacityExceeded)
125        }
126    }
127
128    /// Returns a reference to an element or subslice, without doing bounds checking.
129    #[inline]
130    pub fn get(&self, index: usize) -> Option<&T> {
131        self.0.get(index)
132    }
133
134    /// Returns an iterator over the slice.
135    #[inline]
136    pub fn iter(&self) -> slice::Iter<'_, T> {
137        self.0.iter()
138    }
139
140    /// Returns a mutable iterator over the slice.
141    #[inline]
142    pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> {
143        self.0.iter_mut()
144    }
145
146    /// Consumes the Vec and returns the inner representation.
147    #[inline]
148    #[cfg(not(feature = "alloc"))]
149    pub(crate) fn into_inner(self) -> Inner<T, N> {
150        self.0
151    }
152}
153
154impl<'a, T, const N: usize> IntoIterator for &'a Vec<T, N> {
155    type Item = &'a T;
156    type IntoIter = slice::Iter<'a, T>;
157
158    #[inline]
159    fn into_iter(self) -> Self::IntoIter {
160        self.iter()
161    }
162}
163
164#[cfg(feature = "alloc")]
165impl<T, const N: usize> IntoIterator for Vec<T, N> {
166    type Item = T;
167    type IntoIter = alloc::vec::IntoIter<T>;
168
169    #[inline]
170    fn into_iter(self) -> Self::IntoIter {
171        self.0.into_iter()
172    }
173}
174
175#[cfg(not(feature = "alloc"))]
176impl<T, const N: usize> IntoIterator for Vec<T, N> {
177    type Item = T;
178    type IntoIter = heapless::vec::IntoIter<T, N, usize>;
179
180    #[inline]
181    fn into_iter(self) -> Self::IntoIter {
182        self.0.into_iter()
183    }
184}
185
186impl<T, const N: usize> FromIterator<T> for Vec<T, N> {
187    fn from_iter<I>(iter: I) -> Self
188    where
189        I: IntoIterator<Item = T>,
190    {
191        #[cfg(feature = "alloc")]
192        {
193            let iter = iter.into_iter();
194            let (lower, upper) = iter.size_hint();
195            let reserve = upper.unwrap_or(lower).min(N);
196            let mut v = alloc::vec::Vec::new();
197            if reserve > 0 {
198                v.reserve_exact(reserve);
199            }
200            for item in iter {
201                if v.len() >= N {
202                    panic!("Vec::from_iter overflow");
203                }
204                v.push(item);
205            }
206            Self(v)
207        }
208        #[cfg(not(feature = "alloc"))]
209        {
210            Self(Inner::from_iter(iter))
211        }
212    }
213}
214
215impl<T, const N: usize> hash::Hash for Vec<T, N>
216where
217    T: hash::Hash,
218{
219    #[inline]
220    fn hash<H: hash::Hasher>(&self, state: &mut H) {
221        self.0.hash(state);
222    }
223}
224
225impl<T, const N: usize> PartialEq for Vec<T, N>
226where
227    T: PartialEq,
228{
229    #[inline]
230    fn eq(&self, other: &Self) -> bool {
231        self.0 == other.0
232    }
233}
234
235impl<T, const N: usize> Eq for Vec<T, N> where T: Eq {}
236
237impl<T, const N: usize> Default for Vec<T, N> {
238    #[inline]
239    fn default() -> Self {
240        #[cfg(feature = "alloc")]
241        {
242            Self(Inner::with_capacity(N))
243        }
244        #[cfg(not(feature = "alloc"))]
245        {
246            Self(Inner::new())
247        }
248    }
249}
250
251impl<T, const N: usize> core::ops::Index<usize> for Vec<T, N> {
252    type Output = T;
253
254    #[inline]
255    fn index(&self, index: usize) -> &Self::Output {
256        &self.0[index]
257    }
258}
259
260impl<T, const N: usize> core::ops::Deref for Vec<T, N> {
261    type Target = [T];
262
263    #[inline]
264    fn deref(&self) -> &Self::Target {
265        self.as_slice()
266    }
267}
268
269#[cfg(all(test, feature = "alloc"))]
270mod from_iter_tests {
271    use super::Vec;
272
273    #[test]
274    fn from_iter_collects_up_to_n() {
275        let v: Vec<u8, 4> = [1, 2, 3, 4].into_iter().collect();
276        assert_eq!(v.as_slice(), [1, 2, 3, 4]);
277    }
278
279    #[test]
280    #[should_panic(expected = "Vec::from_iter overflow")]
281    fn from_iter_panics_when_more_than_n() {
282        let _: Vec<u8, 2> = [1_u8, 2, 3].into_iter().collect();
283    }
284
285    #[test]
286    #[should_panic(expected = "Vec::from_iter overflow")]
287    fn from_iter_panics_despite_lying_upper_hint() {
288        struct BadHint<I>(I);
289        impl<I: Iterator<Item = u8>> Iterator for BadHint<I> {
290            type Item = u8;
291            fn next(&mut self) -> Option<Self::Item> {
292                self.0.next()
293            }
294            fn size_hint(&self) -> (usize, Option<usize>) {
295                (0, Some(1))
296            }
297        }
298        let _: Vec<u8, 2> = BadHint([1_u8, 2, 3].into_iter()).collect();
299    }
300}