oxidd_parser/vec2d/
mod.rs

1//! Compact representation of a `Vec<Vec<T>>`
2
3use std::fmt;
4use std::iter::FusedIterator;
5
6pub(crate) mod with_metadata;
7
8/// Compact representation of a `Vec<Vec<T>>`
9#[derive(Clone, PartialEq, Eq)]
10pub struct Vec2d<T>(with_metadata::Vec2d<T, 0>);
11
12impl<T> Default for Vec2d<T> {
13    #[inline(always)]
14    fn default() -> Self {
15        Self(Default::default())
16    }
17}
18
19impl<T> Vec2d<T> {
20    /// Create a new empty `Vec2d`.
21    ///
22    /// This is equivalent to
23    /// [`Self::with_capacity(0, 0)`][Self::with_capacity].
24    #[inline(always)]
25    pub fn new() -> Self {
26        Self::default()
27    }
28
29    /// Create a new empty `Vec2d` with at least the specified capacities.
30    ///
31    /// A `Vec2d` internally contains two [`Vec`]s, one for the elements of all
32    /// the inner vectors and one for the indices where these inner vectors
33    /// begin. `vectors` is the capacity for the latter and `elements_sum` is
34    /// the capacity for the former `Vec`.
35    #[inline(always)]
36    pub fn with_capacity(vectors: usize, elements_sum: usize) -> Self {
37        Self(with_metadata::Vec2d::with_capacity(vectors, elements_sum))
38    }
39
40    /// Reserve space for at least `additional` more inner vectors. Note that
41    /// this will not reserve space for elements of the inner vectors. To that
42    /// end, use [`Self::reserve_elements()`].
43    ///
44    /// This is essentially a wrapper around [`Vec::reserve()`], so the
45    /// documentation there provides more details.
46    #[inline(always)]
47    pub fn reserve_vectors(&mut self, additional: usize) {
48        self.0.reserve_vectors(additional);
49    }
50    /// Reserve space for at least `additional` more elements in the inner
51    /// vectors. The space is shared between the inner vectors: After reserving
52    /// space for `n` additional elements, pushing, e.g., two vectors with `k1 +
53    /// k2 <= n` elements will not lead to a reallocation.
54    ///
55    /// This is essentially a wrapper around [`Vec::reserve()`], so the
56    /// documentation there provides more details.
57    #[inline(always)]
58    pub fn reserve_elements(&mut self, additional: usize) {
59        self.0.reserve_elements(additional);
60    }
61
62    /// Get the number of inner vectors
63    #[inline(always)]
64    pub fn len(&self) -> usize {
65        self.0.len()
66    }
67    /// `true` iff there are no inner vectors
68    ///
69    /// Equivalent to [`self.len() == 0`][Self::len]
70    #[inline(always)]
71    pub fn is_empty(&self) -> bool {
72        self.0.is_empty()
73    }
74
75    /// Get the vector at `index` if there is one
76    #[inline]
77    pub fn get(&self, index: usize) -> Option<&[T]> {
78        Some(self.0.get(index)?.1)
79    }
80    /// Get the vector at `index` if there is one
81    #[inline(always)]
82    pub fn get_mut(&mut self, index: usize) -> Option<&mut [T]> {
83        self.0.get_mut(index)
84    }
85    /// Get the first vector if there is one
86    #[inline]
87    pub fn first(&self) -> Option<&[T]> {
88        Some(self.0.first()?.1)
89    }
90    /// Get the first vector if there is one
91    #[inline(always)]
92    pub fn first_mut(&mut self) -> Option<&mut [T]> {
93        self.0.first_mut()
94    }
95    /// Get the last vector if there is one
96    #[inline]
97    pub fn last(&self) -> Option<&[T]> {
98        Some(self.0.last()?.1)
99    }
100    /// Get the last vector if there is one
101    #[inline(always)]
102    pub fn last_mut(&mut self) -> Option<&mut [T]> {
103        self.0.last_mut()
104    }
105
106    /// Iterate over the inner vector
107    #[inline(always)]
108    pub fn iter(&self) -> Vec2dIter<'_, T> {
109        Vec2dIter(self.0.iter())
110    }
111
112    /// Add an empty inner vector
113    ///
114    /// Elements can be added to that vector using [`Self::push_element()`]
115    #[inline(always)]
116    pub fn push_vec(&mut self) {
117        self.0.push_vec(0);
118    }
119
120    /// Remove the last vector (if there is one)
121    ///
122    /// Returns true iff the outer vector was non-empty before removal.
123    #[inline(always)]
124    pub fn pop_vec(&mut self) -> bool {
125        self.0.pop_vec()
126    }
127
128    /// Truncate the outer vector to `len` inner vectors
129    ///
130    /// If `len` is greater or equal to [`self.len()`][Self::len()], this is a
131    /// no-op.
132    #[inline(always)]
133    pub fn truncate(&mut self, len: usize) {
134        self.0.truncate(len);
135    }
136
137    /// Push an element to the last vector
138    ///
139    /// The vector list must be non-empty.
140    #[track_caller]
141    #[inline(always)]
142    pub fn push_element(&mut self, element: T) {
143        self.0.push_element(element);
144    }
145
146    /// Extend the last vector by the elements from `iter`
147    ///
148    /// There must be at least one inner vector (i.e.,
149    /// [`!self.is_empty()`][Self::is_empty()]).
150    #[track_caller]
151    #[inline(always)]
152    pub fn push_elements(&mut self, iter: impl IntoIterator<Item = T>) {
153        self.0.push_elements(iter);
154    }
155
156    /// Get a slice containing all elements, ignoring the boundaries of the
157    /// inner vectors
158    #[inline(always)]
159    pub fn all_elements(&self) -> &[T] {
160        self.0.all_elements()
161    }
162    /// Get a slice containing all elements, ignoring the boundaries of the
163    /// inner vectors
164    #[inline(always)]
165    pub fn all_elements_mut(&mut self) -> &mut [T] {
166        self.0.all_elements_mut()
167    }
168}
169
170impl<T: Clone> Vec2d<T> {
171    /// Resize the last vector in-place such that its length is equal to
172    /// `new_len`
173    ///
174    /// If `new_len` is greater than the current length, the vector is extended
175    /// by the difference, with each additional slot filled with `value`. If
176    /// `new_len` is less than `len`, the `Vec` is simply truncated.
177    #[track_caller]
178    #[inline(always)]
179    pub fn resize_last(&mut self, new_len: usize, value: T) {
180        self.0.resize_last(new_len, value);
181    }
182}
183
184#[cold]
185#[inline(never)]
186fn panic_bounds_check(len: usize, index: usize) -> ! {
187    panic!("index out of bounds: the len is {len} but the index is {index}");
188}
189
190impl<T> std::ops::Index<usize> for Vec2d<T> {
191    type Output = [T];
192
193    #[track_caller]
194    #[inline(always)]
195    fn index(&self, index: usize) -> &[T] {
196        if let Some(v) = self.get(index) {
197            return v;
198        }
199        panic_bounds_check(self.len(), index)
200    }
201}
202impl<T> std::ops::IndexMut<usize> for Vec2d<T> {
203    #[track_caller]
204    #[inline(always)]
205    fn index_mut(&mut self, index: usize) -> &mut [T] {
206        let len = self.len(); // moved up here due to borrow checker issues
207        if let Some(v) = self.get_mut(index) {
208            return v;
209        }
210        panic_bounds_check(len, index)
211    }
212}
213
214impl<'a, T: Copy> Extend<&'a [T]> for Vec2d<T> {
215    fn extend<I: IntoIterator<Item = &'a [T]>>(&mut self, iter: I) {
216        self.0.extend(iter.into_iter().map(|i| (0, i)));
217    }
218}
219
220impl<'a, T: Copy> FromIterator<&'a [T]> for Vec2d<T> {
221    #[inline(always)]
222    fn from_iter<I: IntoIterator<Item = &'a [T]>>(iter: I) -> Self {
223        let mut vec = Vec2d::new();
224        vec.extend(iter);
225        vec
226    }
227}
228
229impl<T: fmt::Debug> fmt::Debug for Vec2d<T> {
230    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
231        f.debug_list().entries(self.iter()).finish()
232    }
233}
234
235/// Iterator over the inner vectors of a [`Vec2d`]
236#[derive(Clone)]
237pub struct Vec2dIter<'a, T>(with_metadata::Vec2dIter<'a, T, 0>);
238
239impl<'a, T> Iterator for Vec2dIter<'a, T> {
240    type Item = &'a [T];
241
242    #[inline]
243    fn next(&mut self) -> Option<&'a [T]> {
244        Some(self.0.next()?.1)
245    }
246
247    #[inline(always)]
248    fn size_hint(&self) -> (usize, Option<usize>) {
249        self.0.size_hint()
250    }
251
252    // performance optimization
253
254    #[inline(always)]
255    fn count(self) -> usize {
256        self.0.count()
257    }
258    #[inline(always)]
259    fn last(self) -> Option<&'a [T]> {
260        Some(self.0.last()?.1)
261    }
262    #[inline]
263    fn nth(&mut self, n: usize) -> Option<&'a [T]> {
264        Some(self.0.nth(n)?.1)
265    }
266}
267
268impl<T> FusedIterator for Vec2dIter<'_, T> {}
269
270impl<T> ExactSizeIterator for Vec2dIter<'_, T> {
271    #[inline(always)]
272    fn len(&self) -> usize {
273        self.0.len()
274    }
275}
276
277impl<'a, T> DoubleEndedIterator for Vec2dIter<'a, T> {
278    #[inline]
279    fn next_back(&mut self) -> Option<&'a [T]> {
280        Some(self.0.next_back()?.1)
281    }
282
283    // performance optimization
284
285    #[inline]
286    fn nth_back(&mut self, n: usize) -> Option<&'a [T]> {
287        Some(self.0.nth_back(n)?.1)
288    }
289}