1use super::*;
2
3pub trait FlatScanFn {
4 type InputItem;
5 type InputResult;
6 type OutputList: ListFn<End = Self>;
7 type EndList: ListFn<Item = <Self::OutputList as ListFn>::Item>;
8 fn map_item(self, item: Self::InputItem) -> Self::OutputList;
10 fn map_result(self, result: Self::InputResult) -> Self::EndList;
12}
13
14pub enum FlatScanState<I, F>
15where
16 I: ListFn,
17 F: FlatScanFn<InputItem = I::Item>,
18 I::End: ResultFn<Result = F::InputResult>,
19{
20 Begin {
21 flat_scan: F,
22 input_list: I,
23 },
24 OutputList {
25 output_list: F::OutputList,
26 input_list: I,
27 },
28 EndList(F::EndList),
29}
30
31impl<I, F> ListFn for FlatScanState<I, F>
32where
33 I: ListFn,
34 F: FlatScanFn<InputItem = I::Item>,
35 I::End: ResultFn<Result = F::InputResult>,
36{
37 type Item = <F::OutputList as ListFn>::Item;
38 type End = <F::EndList as ListFn>::End;
39 fn next(mut self) -> ListState<Self> {
40 loop {
41 self = match self {
42 FlatScanState::Begin {
43 input_list,
44 flat_scan,
45 } => match input_list.next() {
46 ListState::Some(some) => FlatScanState::OutputList {
47 output_list: flat_scan.map_item(some.first),
48 input_list: some.next,
49 },
50 ListState::End(end) => {
51 FlatScanState::EndList(flat_scan.map_result(end.result()))
52 }
53 },
54 FlatScanState::OutputList {
55 output_list,
56 input_list,
57 } => match output_list.next() {
58 ListState::Some(some) => {
59 return ListState::some(
60 some.first,
61 FlatScanState::OutputList {
62 output_list: some.next,
63 input_list,
64 },
65 )
66 }
67 ListState::End(flat_scan) => FlatScanState::Begin {
68 input_list,
69 flat_scan,
70 },
71 },
72 FlatScanState::EndList(end_list) => {
73 return match end_list.next() {
74 ListState::Some(some) => {
75 ListState::some(some.first, FlatScanState::EndList(some.next))
76 }
77 ListState::End(end) => ListState::End(end),
78 }
79 }
80 }
81 }
82 }
83}
84
85pub trait FlatScan: ListFn {
86 fn flat_scan<F>(self, flat_scan: F) -> FlatScanState<Self, F>
87 where
88 F: FlatScanFn<InputItem = Self::Item>,
89 Self::End: ResultFn<Result = F::InputResult>,
90 {
91 FlatScanState::Begin {
92 input_list: self,
93 flat_scan,
94 }
95 }
96}
97
98impl<S: ListFn> FlatScan for S {}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 struct TestFlatScan();
105
106 impl ResultFn for TestFlatScan {
107 type Result = ();
108 fn result(self) {}
109 }
110
111 impl FlatScanFn for TestFlatScan {
112 type InputItem = ();
113 type InputResult = ();
114 type OutputList = Empty<(), Self>;
115 type EndList = Empty<(), Self>;
116 fn map_item(self, _: ()) -> Self::OutputList {
117 Empty::new(self)
118 }
119 fn map_result(self, _: ()) -> Self::EndList {
120 Empty::new(self)
121 }
122 }
123
124 #[test]
125 fn flat_scan_end() {
126 let x = Empty::<(), ()>::new(());
127 let f = TestFlatScan();
128 let list = x.flat_scan(f);
129 let _list1 = list.next();
130 }
131}