planus/union_vectors/
iterators.rs

1use core::num::NonZeroUsize;
2
3use crate::VectorReadUnion;
4
5use super::UnionVector;
6
7fn div_ceil(lhs: usize, rhs: usize) -> usize {
8    let d = lhs / rhs;
9    let r = lhs % rhs;
10    if r > 0 && rhs > 0 {
11        d + 1
12    } else {
13        d
14    }
15}
16
17/// An iterator over the elements of a [`UnionVector`].
18///
19/// This struct is created by the [`iter`][`UnionVector::iter`] method on [`UnionVector`]s.
20pub struct Iter<'buf, T> {
21    v: UnionVector<'buf, T>,
22}
23
24impl<'buf, T: VectorReadUnion<'buf> + core::fmt::Debug> core::fmt::Debug for Iter<'buf, T> {
25    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
26        f.debug_struct("Iter").field("v", &self.v).finish()
27    }
28}
29
30impl<T> Clone for Iter<'_, T> {
31    #[inline]
32    fn clone(&self) -> Self {
33        Self { v: self.v }
34    }
35}
36
37impl<'buf, T: VectorReadUnion<'buf>> Iter<'buf, T> {
38    #[inline]
39    pub(crate) fn new(v: UnionVector<'buf, T>) -> Self {
40        Self { v }
41    }
42}
43
44impl<'buf, T: VectorReadUnion<'buf>> Iterator for Iter<'buf, T> {
45    type Item = crate::Result<T>;
46
47    #[inline]
48    fn next(&mut self) -> Option<crate::Result<T>> {
49        if let Some((first, remaining)) = self.v.split_first() {
50            self.v = remaining;
51            Some(first)
52        } else {
53            None
54        }
55    }
56
57    #[inline]
58    fn nth(&mut self, n: usize) -> Option<Self::Item> {
59        self.v = self.v.get(n..).unwrap_or_else(|| UnionVector::new_empty());
60        self.next()
61    }
62
63    #[inline]
64    fn size_hint(&self) -> (usize, Option<usize>) {
65        let len = self.len();
66        (len, Some(len))
67    }
68
69    #[inline]
70    fn count(self) -> usize {
71        self.len()
72    }
73
74    #[inline]
75    fn last(self) -> Option<Self::Item> {
76        self.v.last()
77    }
78}
79
80impl<'buf, T: VectorReadUnion<'buf>> core::iter::DoubleEndedIterator for Iter<'buf, T> {
81    #[inline]
82    fn next_back(&mut self) -> Option<Self::Item> {
83        if let Some((last, remaining)) = self.v.split_last() {
84            self.v = remaining;
85            Some(last)
86        } else {
87            None
88        }
89    }
90
91    #[inline]
92    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
93        self.v = unsafe { self.v.get_unchecked(..self.v.len().saturating_sub(n)) };
94        self.next_back()
95    }
96}
97
98impl<'buf, T: VectorReadUnion<'buf>> core::iter::ExactSizeIterator for Iter<'buf, T> {
99    #[inline]
100    fn len(&self) -> usize {
101        self.v.len()
102    }
103}
104
105impl<'buf, T: VectorReadUnion<'buf>> core::iter::FusedIterator for Iter<'buf, T> {}
106
107/// An iterator over a [`UnionVector`] in (non-overlapping) chunks (`chunk_size`
108/// elements at a time), starting at the beginning of the [`UnionVector`].
109///
110/// When the [`UnionVector`] len is not evenly divided by the chunk size, the last
111/// [`UnionVector`] of the iteration will be the remainder.
112///
113/// This struct is created by the [`chunks`][`UnionVector::chunks`] method on [`UnionVector`]s.
114pub struct Chunks<'buf, T> {
115    v: UnionVector<'buf, T>,
116    chunk_size: NonZeroUsize,
117}
118
119impl<'buf, T: VectorReadUnion<'buf> + core::fmt::Debug> core::fmt::Debug for Chunks<'buf, T> {
120    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
121        f.debug_struct("Chunks")
122            .field("v", &self.v)
123            .field("chunk_size", &self.chunk_size)
124            .finish()
125    }
126}
127
128impl<T> Clone for Chunks<'_, T> {
129    #[inline]
130    fn clone(&self) -> Self {
131        Self {
132            v: self.v,
133            chunk_size: self.chunk_size,
134        }
135    }
136}
137
138impl<'buf, T: VectorReadUnion<'buf>> Chunks<'buf, T> {
139    #[inline]
140    pub(crate) fn new(v: UnionVector<'buf, T>, chunk_size: NonZeroUsize) -> Self {
141        Self { v, chunk_size }
142    }
143}
144
145impl<'buf, T: VectorReadUnion<'buf>> Iterator for Chunks<'buf, T> {
146    type Item = UnionVector<'buf, T>;
147
148    #[inline]
149    fn next(&mut self) -> Option<UnionVector<'buf, T>> {
150        if self.v.is_empty() {
151            None
152        } else if let Some((first, remaining)) = self.v.split_at(self.chunk_size.get()) {
153            self.v = remaining;
154            Some(first)
155        } else {
156            Some(core::mem::replace(&mut self.v, UnionVector::new_empty()))
157        }
158    }
159
160    #[inline]
161    fn nth(&mut self, n: usize) -> Option<Self::Item> {
162        let skip = n.saturating_mul(self.chunk_size.get());
163        self.v = self
164            .v
165            .get(skip..)
166            .unwrap_or_else(|| UnionVector::new_empty());
167        self.next()
168    }
169
170    #[inline]
171    fn size_hint(&self) -> (usize, Option<usize>) {
172        let len = self.len();
173        (len, Some(len))
174    }
175
176    #[inline]
177    fn count(self) -> usize {
178        self.len()
179    }
180
181    #[inline]
182    fn last(mut self) -> Option<Self::Item> {
183        self.next_back()
184    }
185}
186
187impl<'buf, T: VectorReadUnion<'buf>> core::iter::DoubleEndedIterator for Chunks<'buf, T> {
188    #[inline]
189    fn next_back(&mut self) -> Option<Self::Item> {
190        if self.v.is_empty() {
191            None
192        } else {
193            let split_point = (self.v.len() - 1) / self.chunk_size * self.chunk_size.get();
194            let (remaining, last) = unsafe { self.v.split_at_unchecked(split_point) };
195            self.v = remaining;
196            Some(last)
197        }
198    }
199
200    #[inline]
201    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
202        if n > 0 {
203            // This will be strictly lower than the len
204            let new_chunk_count = self.len().saturating_sub(n);
205            // Note that all of the remaining chunks will be full chunks
206            // This makes it easy to calculate the new size
207            self.v = unsafe {
208                self.v
209                    .get_unchecked(..new_chunk_count * self.chunk_size.get())
210            };
211        }
212        self.next_back()
213    }
214}
215
216impl<'buf, T: VectorReadUnion<'buf>> core::iter::ExactSizeIterator for Chunks<'buf, T> {
217    #[inline]
218    fn len(&self) -> usize {
219        let len = self.v.len();
220        div_ceil(len, self.chunk_size.get())
221    }
222}
223
224impl<'buf, T: VectorReadUnion<'buf>> core::iter::FusedIterator for Chunks<'buf, T> {}
225
226/// An iterator over a [`UnionVector`] in (non-overlapping) chunks (`chunk_size`
227/// elements at a time), starting at the end of the [`UnionVector`].
228///
229/// When the [`UnionVector`] len is not evenly divided by the chunk size, the last [`UnionVector`]
230/// of the iteration will be the remainder.
231///
232/// This struct is created by the [`rchunks`][`UnionVector::rchunks`] method on [`UnionVector`]s.
233pub struct RChunks<'buf, T> {
234    v: UnionVector<'buf, T>,
235    chunk_size: NonZeroUsize,
236}
237
238impl<'buf, T: VectorReadUnion<'buf> + core::fmt::Debug> core::fmt::Debug for RChunks<'buf, T> {
239    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
240        f.debug_struct("RChunks")
241            .field("v", &self.v)
242            .field("chunk_size", &self.chunk_size)
243            .finish()
244    }
245}
246
247impl<T> Clone for RChunks<'_, T> {
248    #[inline]
249    fn clone(&self) -> Self {
250        Self {
251            v: self.v,
252            chunk_size: self.chunk_size,
253        }
254    }
255}
256
257impl<'buf, T: VectorReadUnion<'buf>> RChunks<'buf, T> {
258    #[inline]
259    pub(crate) fn new(v: UnionVector<'buf, T>, chunk_size: NonZeroUsize) -> Self {
260        Self { v, chunk_size }
261    }
262}
263
264impl<'buf, T: VectorReadUnion<'buf>> Iterator for RChunks<'buf, T> {
265    type Item = UnionVector<'buf, T>;
266
267    #[inline]
268    fn next(&mut self) -> Option<UnionVector<'buf, T>> {
269        if self.v.is_empty() {
270            None
271        } else {
272            let (remaining, cur) = unsafe {
273                self.v
274                    .split_at_unchecked(self.v.len().saturating_sub(self.chunk_size.get()))
275            };
276            self.v = remaining;
277            Some(cur)
278        }
279    }
280
281    #[inline]
282    fn nth(&mut self, n: usize) -> Option<Self::Item> {
283        self.v = unsafe {
284            self.v.get_unchecked(
285                ..self
286                    .v
287                    .len()
288                    .saturating_sub(n.saturating_mul(self.chunk_size.get())),
289            )
290        };
291        self.next()
292    }
293
294    #[inline]
295    fn size_hint(&self) -> (usize, Option<usize>) {
296        let len = self.len();
297        (len, Some(len))
298    }
299
300    #[inline]
301    fn count(self) -> usize {
302        self.len()
303    }
304
305    #[inline]
306    fn last(mut self) -> Option<Self::Item> {
307        self.next_back()
308    }
309}
310
311impl<'buf, T: VectorReadUnion<'buf>> core::iter::DoubleEndedIterator for RChunks<'buf, T> {
312    #[inline]
313    fn next_back(&mut self) -> Option<Self::Item> {
314        if self.v.is_empty() {
315            None
316        } else {
317            let mid = ((self.v.len() - 1) % self.chunk_size) + 1;
318            let (start, remaining) = unsafe { self.v.split_at_unchecked(mid) };
319            self.v = remaining;
320            Some(start)
321        }
322    }
323
324    #[inline]
325    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
326        if n > 0 {
327            // This will be strictly lower than the len
328            let new_chunk_count = self.len().saturating_sub(n);
329            // Note that all of the remaining chunks will be full chunks
330            // This makes it easy to calculate the new size
331            self.v = unsafe {
332                self.v
333                    .get_unchecked(self.v.len() - (new_chunk_count * self.chunk_size.get())..)
334            };
335        }
336        self.next_back()
337    }
338}
339
340impl<'buf, T: VectorReadUnion<'buf>> core::iter::ExactSizeIterator for RChunks<'buf, T> {
341    #[inline]
342    fn len(&self) -> usize {
343        div_ceil(self.v.len(), self.chunk_size.get())
344    }
345}
346
347impl<'buf, T: VectorReadUnion<'buf>> core::iter::FusedIterator for RChunks<'buf, T> {}
348
349/// An iterator over a [`UnionVector`] in (non-overlapping) chunks (`chunk_size` elements
350/// at a time), starting at the beginning of the slice.
351///
352/// When the [`UnionVector`] len is not evenly divided by the chunk size, the last
353/// up to `chunk_size-1` elements will be omitted but can be retrieved from
354/// the [`remainder`] function from the iterator.
355///
356/// This struct is created by the [`chunks_exact`] method on [`UnionVector`]s.
357///
358/// [`chunks_exact`]: UnionVector::chunks_exact
359/// [`remainder`]: ChunksExact::remainder
360pub struct ChunksExact<'buf, T> {
361    v: UnionVector<'buf, T>,
362    rem: UnionVector<'buf, T>,
363    chunk_size: NonZeroUsize,
364}
365
366impl<'buf, T: VectorReadUnion<'buf> + core::fmt::Debug> core::fmt::Debug for ChunksExact<'buf, T> {
367    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
368        f.debug_struct("ChunksExact")
369            .field("v", &self.v)
370            .field("rem", &self.rem)
371            .field("chunk_size", &self.chunk_size)
372            .finish()
373    }
374}
375
376impl<T> Clone for ChunksExact<'_, T> {
377    #[inline]
378    fn clone(&self) -> Self {
379        Self {
380            v: self.v,
381            rem: self.rem,
382            chunk_size: self.chunk_size,
383        }
384    }
385}
386
387impl<'buf, T: VectorReadUnion<'buf>> ChunksExact<'buf, T> {
388    #[inline]
389    pub(crate) fn new(v: UnionVector<'buf, T>, chunk_size: NonZeroUsize) -> Self {
390        let len = v.len() / chunk_size.get() * chunk_size.get();
391        let (v, rem) = unsafe { v.split_at_unchecked(len) };
392        Self { v, rem, chunk_size }
393    }
394
395    /// Returns the remainder of the original vector that is not going to be
396    /// returned by the iterator. The returned vector has at most `chunk_size-1`
397    /// elements.
398    #[inline]
399    #[must_use]
400    pub fn remainder(&self) -> UnionVector<'buf, T> {
401        self.rem
402    }
403}
404
405impl<'buf, T: VectorReadUnion<'buf>> Iterator for ChunksExact<'buf, T> {
406    type Item = UnionVector<'buf, T>;
407
408    #[inline]
409    fn next(&mut self) -> Option<UnionVector<'buf, T>> {
410        debug_assert!(self.v.len() % self.chunk_size == 0);
411        if self.v.is_empty() {
412            None
413        } else {
414            let (first, remaining) = unsafe { self.v.split_at_unchecked(self.chunk_size.get()) };
415            self.v = remaining;
416            Some(first)
417        }
418    }
419
420    #[inline]
421    fn nth(&mut self, n: usize) -> Option<Self::Item> {
422        let skip = n.saturating_mul(self.chunk_size.get());
423        self.v = self
424            .v
425            .get(skip..)
426            .unwrap_or_else(|| UnionVector::new_empty());
427        self.next()
428    }
429
430    #[inline]
431    fn size_hint(&self) -> (usize, Option<usize>) {
432        let len = self.len();
433        (len, Some(len))
434    }
435
436    #[inline]
437    fn count(self) -> usize {
438        self.len()
439    }
440
441    #[inline]
442    fn last(mut self) -> Option<Self::Item> {
443        self.next_back()
444    }
445}
446
447impl<'buf, T: VectorReadUnion<'buf>> core::iter::DoubleEndedIterator for ChunksExact<'buf, T> {
448    #[inline]
449    fn next_back(&mut self) -> Option<Self::Item> {
450        debug_assert!(self.v.len() % self.chunk_size == 0);
451        if self.v.is_empty() {
452            None
453        } else {
454            let (remaining, last) = unsafe {
455                self.v
456                    .split_at_unchecked(self.v.len() - self.chunk_size.get())
457            };
458            self.v = remaining;
459            Some(last)
460        }
461    }
462
463    #[inline]
464    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
465        self.v = unsafe {
466            self.v.get_unchecked(
467                ..self
468                    .v
469                    .len()
470                    .saturating_sub(n.saturating_mul(self.chunk_size.get())),
471            )
472        };
473        self.next_back()
474    }
475}
476
477impl<'buf, T: VectorReadUnion<'buf>> core::iter::ExactSizeIterator for ChunksExact<'buf, T> {
478    #[inline]
479    fn len(&self) -> usize {
480        self.v.len() / self.chunk_size
481    }
482}
483
484impl<'buf, T: VectorReadUnion<'buf>> core::iter::FusedIterator for ChunksExact<'buf, T> {}
485
486/// An iterator over a [`UnionVector`] in (non-overlapping) chunks (`chunk_size`
487/// elements at a time), starting at the end of the slice.
488///
489/// When the [`UnionVector`] len is not evenly divided by the chunk size, the last
490/// up to `chunk_size-1` elements will be omitted but can be retrieved from
491/// the [`remainder`] function from the iterator.
492///
493/// This struct is created by the [`rchunks_exact`] method on [`UnionVector`]s.
494///
495/// [`remainder`]: RChunksExact::remainder
496/// [`rchunks_exact`]: UnionVector::rchunks_exact
497pub struct RChunksExact<'buf, T> {
498    v: UnionVector<'buf, T>,
499    rem: UnionVector<'buf, T>,
500    chunk_size: NonZeroUsize,
501}
502
503impl<'buf, T: VectorReadUnion<'buf> + core::fmt::Debug> core::fmt::Debug for RChunksExact<'buf, T> {
504    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
505        f.debug_struct("RChunksExact")
506            .field("v", &self.v)
507            .field("rem", &self.rem)
508            .field("chunk_size", &self.chunk_size)
509            .finish()
510    }
511}
512
513impl<T> Clone for RChunksExact<'_, T> {
514    #[inline]
515    fn clone(&self) -> Self {
516        Self {
517            v: self.v,
518            rem: self.rem,
519            chunk_size: self.chunk_size,
520        }
521    }
522}
523
524impl<'buf, T: VectorReadUnion<'buf>> RChunksExact<'buf, T> {
525    #[inline]
526    pub(crate) fn new(v: UnionVector<'buf, T>, chunk_size: NonZeroUsize) -> Self {
527        let rem_size = v.len() % chunk_size;
528        let (rem, v) = unsafe { v.split_at_unchecked(rem_size) };
529        Self { v, rem, chunk_size }
530    }
531
532    /// Returns the remainder of the original vector that is not going to be
533    /// returned by the iterator. The returned vector has at most `chunk_size-1`
534    /// elements.
535    #[inline]
536    #[must_use]
537    pub fn remainder(&self) -> UnionVector<'buf, T> {
538        self.rem
539    }
540}
541
542impl<'buf, T: VectorReadUnion<'buf>> Iterator for RChunksExact<'buf, T> {
543    type Item = UnionVector<'buf, T>;
544
545    #[inline]
546    fn next(&mut self) -> Option<UnionVector<'buf, T>> {
547        debug_assert!(self.v.len() % self.chunk_size == 0);
548        if self.v.is_empty() {
549            None
550        } else {
551            let (remaining, last) = unsafe {
552                self.v
553                    .split_at_unchecked(self.v.len() - self.chunk_size.get())
554            };
555            self.v = remaining;
556            Some(last)
557        }
558    }
559
560    #[inline]
561    fn nth(&mut self, n: usize) -> Option<Self::Item> {
562        self.v = unsafe {
563            self.v.get_unchecked(
564                ..self
565                    .v
566                    .len()
567                    .saturating_sub(n.saturating_mul(self.chunk_size.get())),
568            )
569        };
570        self.next()
571    }
572
573    #[inline]
574    fn size_hint(&self) -> (usize, Option<usize>) {
575        let len = self.len();
576        (len, Some(len))
577    }
578
579    #[inline]
580    fn count(self) -> usize {
581        self.len()
582    }
583
584    #[inline]
585    fn last(mut self) -> Option<Self::Item> {
586        self.next_back()
587    }
588}
589
590impl<'buf, T: VectorReadUnion<'buf>> core::iter::DoubleEndedIterator for RChunksExact<'buf, T> {
591    #[inline]
592    fn next_back(&mut self) -> Option<Self::Item> {
593        debug_assert!(self.v.len() % self.chunk_size == 0);
594        if self.v.is_empty() {
595            None
596        } else {
597            let (first, remaining) = unsafe { self.v.split_at_unchecked(self.chunk_size.get()) };
598            self.v = remaining;
599            Some(first)
600        }
601    }
602
603    #[inline]
604    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
605        let skip = n.saturating_mul(self.chunk_size.get());
606        self.v = self
607            .v
608            .get(skip..)
609            .unwrap_or_else(|| UnionVector::new_empty());
610        self.next_back()
611    }
612}
613
614impl<'buf, T: VectorReadUnion<'buf>> core::iter::ExactSizeIterator for RChunksExact<'buf, T> {
615    #[inline]
616    fn len(&self) -> usize {
617        self.v.len() / self.chunk_size
618    }
619}
620
621impl<'buf, T: VectorReadUnion<'buf>> core::iter::FusedIterator for RChunksExact<'buf, T> {}
622
623/// An iterator over overlapping sub-vectors of length `size`.
624///
625/// This struct is created by the [`windows`] method on [`UnionVector`]s.
626///
627/// [`windows`]: UnionVector::windows
628pub struct Windows<'buf, T> {
629    v: UnionVector<'buf, T>,
630    size: NonZeroUsize,
631}
632
633impl<'buf, T: VectorReadUnion<'buf> + core::fmt::Debug> core::fmt::Debug for Windows<'buf, T> {
634    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
635        f.debug_struct("Windows")
636            .field("v", &self.v)
637            .field("size", &self.size)
638            .finish()
639    }
640}
641
642impl<T> Clone for Windows<'_, T> {
643    #[inline]
644    fn clone(&self) -> Self {
645        Self {
646            v: self.v,
647            size: self.size,
648        }
649    }
650}
651
652impl<'buf, T: VectorReadUnion<'buf>> Windows<'buf, T> {
653    #[inline]
654    pub(crate) fn new(v: UnionVector<'buf, T>, size: NonZeroUsize) -> Self {
655        Self { v, size }
656    }
657}
658
659impl<'buf, T: VectorReadUnion<'buf>> Iterator for Windows<'buf, T> {
660    type Item = UnionVector<'buf, T>;
661
662    #[inline]
663    fn next(&mut self) -> Option<UnionVector<'buf, T>> {
664        let window = self.v.get(..self.size.get())?;
665        self.v = unsafe { self.v.get_unchecked(1..) };
666        Some(window)
667    }
668
669    #[inline]
670    fn nth(&mut self, n: usize) -> Option<Self::Item> {
671        self.v = self.v.get(n..).unwrap_or_else(|| UnionVector::new_empty());
672        self.next()
673    }
674
675    #[inline]
676    fn size_hint(&self) -> (usize, Option<usize>) {
677        let len = self.len();
678        (len, Some(len))
679    }
680
681    #[inline]
682    fn count(self) -> usize {
683        self.len()
684    }
685
686    #[inline]
687    fn last(mut self) -> Option<Self::Item> {
688        self.next_back()
689    }
690}
691
692impl<'buf, T: VectorReadUnion<'buf>> core::iter::DoubleEndedIterator for Windows<'buf, T> {
693    #[inline]
694    fn next_back(&mut self) -> Option<Self::Item> {
695        let index = self.v.len().checked_sub(self.size.get())?;
696        let window = unsafe { self.v.get_unchecked(index..) };
697        self.v = unsafe { self.v.get_unchecked(..self.v.len() - 1) };
698        Some(window)
699    }
700
701    #[inline]
702    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
703        self.v = unsafe { self.v.get_unchecked(..self.v.len().saturating_sub(n)) };
704        self.next_back()
705    }
706}
707
708impl<'buf, T: VectorReadUnion<'buf>> core::iter::ExactSizeIterator for Windows<'buf, T> {
709    #[inline]
710    fn len(&self) -> usize {
711        self.v.len().saturating_sub(self.size.get() - 1)
712    }
713}
714
715impl<'buf, T: VectorReadUnion<'buf>> core::iter::FusedIterator for Windows<'buf, T> {}