1use super::*;
2
3pub trait FlatMapFn {
4 type Input;
5 type OutputList: ListFn;
6 fn map(&self, input: Self::Input) -> Self::OutputList;
8}
9
10pub struct FlatMapList<I: ListFn, F: FlatMapFn<Input = I::Item>> {
11 flat_map: F,
12 input_list: I,
13 output_list: Option<F::OutputList>,
14}
15
16impl<I: ListFn, F: FlatMapFn<Input = I::Item>> ListFn for FlatMapList<I, F> {
17 type Item = <F::OutputList as ListFn>::Item;
18 type End = I::End;
19 fn next(mut self) -> ListState<Self> {
20 loop {
21 match self.output_list {
22 Some(item_list) => match item_list.next() {
23 ListState::Some(some) => {
24 return ListState::some(
25 some.first,
26 FlatMapList {
27 flat_map: self.flat_map,
28 input_list: self.input_list,
29 output_list: Some(some.next),
30 },
31 )
32 }
33 ListState::End(..) => self.output_list = None,
34 },
35 None => match self.input_list.next() {
36 ListState::Some(some) => {
37 self.input_list = some.next;
38 self.output_list = Some(self.flat_map.map(some.first));
39 }
40 ListState::End(end) => return ListState::End(end),
41 },
42 }
43 }
44 }
45}
46
47pub trait FlatMap: ListFn {
48 fn flat_map<F: FlatMapFn<Input = Self::Item>>(self, flat_map: F) -> FlatMapList<Self, F> {
49 FlatMapList {
50 input_list: self,
51 flat_map,
52 output_list: None,
53 }
54 }
55}
56
57impl<S: ListFn> FlatMap for S {}