board_game/util/
iter.rs

1use std::ops::ControlFlow;
2
3use internal_iterator::InternalIterator;
4
5// TODO replace with default wrapper once https://github.com/jDomantas/internal-iterator/pull/11 is merged
6#[derive(Debug, Clone)]
7pub struct ClonableInternal<I: Iterator> {
8    iter: I,
9}
10
11impl<I: Iterator> ClonableInternal<I> {
12    pub fn new(iter: I) -> Self {
13        Self { iter }
14    }
15}
16
17impl<I: Iterator> InternalIterator for ClonableInternal<I> {
18    type Item = I::Item;
19
20    fn try_for_each<R, F>(mut self, f: F) -> ControlFlow<R>
21    where
22        F: FnMut(Self::Item) -> ControlFlow<R>,
23    {
24        self.iter.try_for_each(f)
25    }
26
27    fn count(self) -> usize {
28        self.iter.count()
29    }
30}
31
32#[derive(Debug, Clone)]
33pub struct PureMap<I, F> {
34    inner: I,
35    f: F,
36}
37
38pub trait IterExt: Iterator {
39    /// Pure version of [Iterator::map] that assumes the mapping function does not have side effects.
40    /// This means that implemented functions (like [Self::count], [Self::nth], ...) are allowed to skip calling the mapping function if possible.
41    /// [Iterator::map] already does this do some extend, but only for a limited set of functions.
42    fn pure_map<B, F: Fn(Self::Item) -> B>(self, f: F) -> PureMap<Self, F>
43    where
44        Self: Sized,
45    {
46        PureMap { inner: self, f }
47    }
48}
49
50impl<I: Iterator> IterExt for I {}
51
52impl<I: Iterator, B, F: Fn(I::Item) -> B> Iterator for PureMap<I, F> {
53    type Item = B;
54
55    fn next(&mut self) -> Option<Self::Item> {
56        self.inner.next().map(&self.f)
57    }
58
59    fn size_hint(&self) -> (usize, Option<usize>) {
60        self.inner.size_hint()
61    }
62
63    fn count(self) -> usize
64    where
65        Self: Sized,
66    {
67        self.inner.count()
68    }
69
70    fn last(self) -> Option<Self::Item>
71    where
72        Self: Sized,
73    {
74        self.inner.last().map(&self.f)
75    }
76
77    fn nth(&mut self, n: usize) -> Option<Self::Item> {
78        self.inner.nth(n).map(&self.f)
79    }
80}
81
82impl<I: ExactSizeIterator, B, F: Fn(I::Item) -> B> ExactSizeIterator for PureMap<I, F> {
83    fn len(&self) -> usize {
84        self.inner.len()
85    }
86}