irox_tools/iterators/
zip.rs

1// SPDX-License-Identifier: MIT
2// Copyright 2025 IROX Contributors
3//
4
5use crate::array;
6use crate::buf::{Buffer, RoundBuffer};
7use crate::iterators::LendingIterator;
8
9///
10/// Struct that allows zipping iterators in quantities larger than 2.
11pub struct Zipping<'a, const N: usize, T> {
12    iters: [core::slice::Iter<'a, T>; N],
13}
14
15macro_rules! impl_zipping {
16    (<$n: tt>) => {
17        impl<'a, T: Copy> Iterator for Zipping<'a, $n, T> {
18            type Item = [T;$n];
19
20            fn next(&mut self) -> Option<Self::Item> {
21                let mut i = self.iters.iter_mut();
22                let out : [T;$n] = array![
23                    i.next()?.next().copied()?;$n
24                ];
25                Some(out)
26            }
27        }
28        impl<'a, T> From<[core::slice::Iter<'a, T>; $n]> for Zipping<'a, $n, T> {
29            fn from(iters: [core::slice::Iter<'a, T>; $n]) -> Self {
30                Self {
31                    iters
32                }
33            }
34        }
35    };
36    ($($n:tt),+) => (
37        $(
38            impl_zipping!(<$n>);
39        )*
40    )
41    ;
42}
43impl_zipping!(2, 3, 4, 5, 6, 7, 8, 16, 32, 64);
44
45pub struct Windows<'a, const N: usize, T> {
46    iter: core::slice::Iter<'a, T>,
47    buf: RoundBuffer<N, T>,
48}
49impl<'a, const N: usize, T> Windows<'a, N, T> {
50    pub fn new(iter: core::slice::Iter<'a, T>) -> Self {
51        Self {
52            iter,
53            buf: RoundBuffer::new(),
54        }
55    }
56}
57
58macro_rules! impl_windows {
59    (<$n: tt>) => {
60        impl<'a, T: Copy> LendingIterator for Windows<'a, $n, T> where Self: 'a {
61        type Item<'b> = [&'b T; $n] where Self: 'b;
62
63        fn next_ref(&mut self) -> Option<Self::Item<'_>> {
64            if !self.buf.is_full() {
65                while !self.buf.is_full() {
66                    self.buf.push(self.iter.next().copied()?).ok()?;
67                }
68            } else {
69                self.buf.pop_front()?;
70                self.buf.push(self.iter.next().copied()?).ok()?;
71            }
72            let mut iter = self.buf.iter();
73            let arr = array![iter.next()?;$n];
74            Some(arr)
75        }
76    }
77    };
78    ($($n:tt),+) => (
79        $(
80            impl_windows!(<$n>);
81        )*
82    )
83    ;
84}
85impl_windows!(2, 3, 4, 5, 6, 7, 8, 16, 32, 64);
86#[cfg(test)]
87mod tests {
88    use crate::hex;
89    use crate::iterators::{LendingIterator, Windows};
90
91    #[test]
92    pub fn testwindows() {
93        let a: [u8; 16] = hex!("000102030405060708090A0B0C0D0E0F");
94        let mut iter = Windows::<2, _>::new(a.iter());
95        assert_eq!(iter.next_ref(), Some([&0x00, &0x01]));
96        assert_eq!(iter.next_ref(), Some([&0x01, &0x02]));
97        assert_eq!(iter.next_ref(), Some([&0x02, &0x03]));
98        assert_eq!(iter.next_ref(), Some([&0x03, &0x04]));
99        assert_eq!(iter.next_ref(), Some([&0x04, &0x05]));
100        assert_eq!(iter.next_ref(), Some([&0x05, &0x06]));
101        assert_eq!(iter.next_ref(), Some([&0x06, &0x07]));
102        assert_eq!(iter.next_ref(), Some([&0x07, &0x08]));
103        assert_eq!(iter.next_ref(), Some([&0x08, &0x09]));
104        assert_eq!(iter.next_ref(), Some([&0x09, &0x0A]));
105        assert_eq!(iter.next_ref(), Some([&0x0A, &0x0B]));
106        assert_eq!(iter.next_ref(), Some([&0x0B, &0x0C]));
107        assert_eq!(iter.next_ref(), Some([&0x0C, &0x0D]));
108        assert_eq!(iter.next_ref(), Some([&0x0D, &0x0E]));
109        assert_eq!(iter.next_ref(), Some([&0x0E, &0x0F]));
110    }
111}