Skip to main content

wonfy_tools/util/iter/
windows_iter.rs

1use std::collections::VecDeque;
2
3pub trait IterWindows: Iterator {
4    fn windows(self, size: usize) -> Windows<Self>
5    where
6        Self: Sized + Iterator,
7        Self::Item: Clone,
8    {
9        Windows::new(self, size)
10    }
11}
12
13#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
14#[derive(Clone, Debug)]
15pub struct Windows<I>
16where
17    I: Iterator,
18{
19    iter: I,
20    size: usize,
21    last: Option<VecDeque<I::Item>>,
22}
23
24impl<I> Windows<I>
25where
26    I: Iterator,
27{
28    pub fn new(iter: I, size: usize) -> Self {
29        Self {
30            iter,
31            size,
32            last: None,
33        }
34    }
35}
36
37impl<I> Iterator for Windows<I>
38where
39    I: Iterator,
40    I::Item: Clone,
41{
42    type Item = VecDeque<I::Item>;
43
44    fn next(&mut self) -> Option<Self::Item> {
45        if let Some(new) = self.iter.next() {
46            if let Some(ref mut last) = self.last {
47                last.pop_back();
48                last.push_front(new);
49                Some(last.clone())
50            } else {
51                use std::iter::once;
52                let iter = once(new).chain(&mut self.iter).take(self.size);
53                self.last = Some(iter.collect());
54                self.last.clone()
55            }
56        } else {
57            None
58        }
59    }
60
61    fn size_hint(&self) -> (usize, Option<usize>) {
62        let mut sh = self.iter.size_hint();
63
64        if self.last.is_none() {
65            let (mut low, mut hi) = sh;
66            low = low.saturating_sub(self.size);
67            hi = hi.map(|elt| elt.saturating_sub(self.size));
68            sh = (low, hi)
69        }
70
71        sh
72    }
73}
74
75impl<T> IterWindows for T where T: Iterator + ?Sized {}