1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use crate::{normalized_actions::NormalizedAction, ActionSplit, FlattenSpecified};

impl<T: Sized, V: NormalizedAction> ActionIter<V> for T where T: Iterator<Item = V> {}

pub trait ActionIter<V: NormalizedAction>: Iterator<Item = V> {
    fn flatten_specified<R, W, T>(self, wanted: W, transform: T) -> FlattenSpecified<V, Self, W, T>
    where
        Self: Sized,
        R: Clone,
        W: Fn(&V) -> Option<&R>,
        T: Fn(R) -> Vec<V>,
    {
        FlattenSpecified::new(self, wanted, transform)
    }

    fn count_action(self, action: impl Fn(&V) -> bool) -> usize
    where
        Self: Sized,
    {
        let mut i = 0;
        self.into_iter().fold((), |_, x| {
            i += action(&x) as usize;
        });

        i
    }

    fn count_actions<const N: usize>(self, action: [fn(&V) -> bool; N]) -> usize
    where
        Self: Sized,
    {
        let mut i = 0;
        self.into_iter().fold((), |_, x| {
            i += action.iter().any(|ptr| ptr(&x)) as usize;
        });

        i
    }

    fn action_split<FromI, Fns>(self, filters: Fns) -> FromI
    where
        Self: Sized + ActionSplit<FromI, Fns, V>,
    {
        ActionSplit::action_split_impl(self, filters)
    }

    fn action_split_ref<FromI, Fns>(self, filters: &Fns) -> FromI
    where
        Self: Sized + ActionSplit<FromI, Fns, V>,
    {
        ActionSplit::action_split_ref_impl(self, filters)
    }

    fn action_split_out<FromI, Fns>(self, filters: Fns) -> (FromI, Vec<V>)
    where
        Self: Sized + ActionSplit<FromI, Fns, V>,
    {
        ActionSplit::action_split_out_impl(self, filters)
    }

    fn action_split_out_ref<FromI, Fns>(self, filters: &Fns) -> (FromI, Vec<V>)
    where
        Self: Sized + ActionSplit<FromI, Fns, V>,
    {
        ActionSplit::action_split_out_ref_impl(self, filters)
    }

    fn collect_action_vec<R>(self, filter: fn(V) -> Option<R>) -> Vec<R>
    where
        Self: Sized,
    {
        let (low, _) = self.size_hint();
        self.into_iter()
            .fold(Vec::with_capacity(low), |mut acc, x| {
                if let Some(valid) = filter(x) {
                    acc.push(valid)
                }
                acc
            })
    }

    fn collect_action<R, I: Default + Extend<R>>(self, filter: impl Fn(V) -> Option<R>) -> I
    where
        Self: Sized,
    {
        self.into_iter().fold(I::default(), |mut acc, x| {
            if let Some(valid) = filter(x) {
                acc.extend(std::iter::once(valid))
            }
            acc
        })
    }
}