Skip to main content

nanvm_lib/common/
iter.rs

1use core::iter::{from_fn, once};
2
3use crate::common::either::Either;
4
5pub trait Iter: Sized + Iterator {
6    /// See https://doc.rust-lang.org/std/iter/struct.Intersperse.html
7    fn intersperse_(self, sep: Self::Item) -> impl Iterator<Item = Self::Item>
8    where
9        Self::Item: Clone,
10    {
11        self.flat_map(move |x| [sep.clone(), x]).skip(1)
12    }
13
14    //
15    fn try_flatten<I: IntoIterator, E>(self) -> impl Iterator<Item = Result<I::Item, E>>
16    where
17        Self: Iterator<Item = Result<I, E>>,
18    {
19        self.flat_map(|v| match v {
20            Err(e) => Either::Left(once(Err(e))),
21            Ok(i) => Either::Right(i.into_iter().map(Result::Ok)),
22        })
23    }
24
25    /// Walks `self` and `j` together to the end of the longer one: each item
26    /// is a pair with at least one side present, and the shorter side is
27    /// `None` past its end.
28    fn zip_longest<J: IntoIterator>(
29        self,
30        j: J,
31    ) -> impl Iterator<Item = (Option<Self::Item>, Option<J::Item>)> {
32        let mut i = self.fuse();
33        let mut j = j.into_iter().fuse();
34        from_fn(move || match (i.next(), j.next()) {
35            (None, None) => None,
36            pair => Some(pair),
37        })
38    }
39
40    /// See https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.eq_by
41    fn eq_by_<J: Iterator>(self, j: J, mut cmp: impl FnMut(&Self::Item, &J::Item) -> bool) -> bool {
42        self.zip_longest(j).all(|pair| match pair {
43            (Some(x), Some(y)) => cmp(&x, &y),
44            _ => false,
45        })
46    }
47}
48
49impl<T: Sized + Iterator> Iter for T {}
50
51#[cfg(test)]
52mod test {
53    use super::Iter;
54
55    #[test]
56    fn zip_longest_same_length() {
57        let pairs: Vec<_> = [1, 2].into_iter().zip_longest(['a', 'b']).collect();
58        assert_eq!(pairs, [(Some(1), Some('a')), (Some(2), Some('b'))]);
59    }
60
61    #[test]
62    fn zip_longest_left_longer() {
63        let pairs: Vec<_> = [1, 2].into_iter().zip_longest(['a']).collect();
64        assert_eq!(pairs, [(Some(1), Some('a')), (Some(2), None)]);
65    }
66
67    #[test]
68    fn zip_longest_right_longer() {
69        let pairs: Vec<_> = [1].into_iter().zip_longest(['a', 'b']).collect();
70        assert_eq!(pairs, [(Some(1), Some('a')), (None, Some('b'))]);
71    }
72
73    #[test]
74    fn zip_longest_empty() {
75        let pairs: Vec<_> = [0; 0].into_iter().zip_longest(['a'; 0]).collect();
76        assert_eq!(pairs, []);
77    }
78
79    #[test]
80    fn eq_by_() {
81        let eq = |a: &i32, b: &i32| a == b;
82        assert!([1, 2].into_iter().eq_by_([1, 2].into_iter(), eq));
83        assert!(![1, 2].into_iter().eq_by_([1, 3].into_iter(), eq));
84        assert!(![1, 2].into_iter().eq_by_([1].into_iter(), eq));
85        assert!(![1].into_iter().eq_by_([1, 2].into_iter(), eq));
86        assert!([].into_iter().eq_by_([].into_iter(), eq));
87    }
88}