1#![no_std]
2
3macro_rules! impl_iter_enum {
50 (
51 $EnumId:ident,
52 $IntoTraitId:ident,
53 $((
54 $A:ident,
55 $iter_enum_a:ident,
56 ($($Before:ident),*),($($After:ident),*)
57 )),*,
58 ) => {
59 #[derive(Clone, Debug)]
60 pub enum $EnumId<$($A),*> {
61 $($A($A),)*
62 }
63
64 impl<I, $($A: Iterator<Item = I>),*> Iterator for $EnumId<$($A),*> {
65 type Item = I;
66 fn next(&mut self) -> Option<Self::Item> {
67 match self {
68 $(Self::$A(inner) => inner.next()),*
69 }
70 }
71 }
72
73 pub trait $IntoTraitId: Sized {
74 $(
75 fn $iter_enum_a<$($Before,)*$($After,)*>(self) -> $EnumId<$($Before,)* Self, $($After,)*> {
76 $EnumId::$A(self)
77 }
78 )*
79 }
80
81 impl<T: Iterator> $IntoTraitId for T {}
82 };
83}
84
85impl_iter_enum!(
86 IterEnum2,
87 IntoIterEnum2,
88 (A, iter_enum_2a, (), (B)),
89 (B, iter_enum_2b, (A), ()),
90);
91
92impl_iter_enum!(
93 IterEnum3,
94 IntoIterEnum3,
95 (A, iter_enum_3a, (), (B, C)),
96 (B, iter_enum_3b, (A), (C)),
97 (C, iter_enum_3c, (A, B), ()),
98);
99
100impl_iter_enum!(
101 IterEnum4,
102 IntoIterEnum4,
103 (A, iter_enum_4a, (), (B, C, D)),
104 (B, iter_enum_4b, (A), (C, D)),
105 (C, iter_enum_4c, (A, B), (D)),
106 (D, iter_enum_4d, (A, B, C), ()),
107);
108
109impl_iter_enum!(
110 IterEnum5,
111 IntoIterEnum5,
112 (A, iter_enum_5a, (), (B, C, D, E)),
113 (B, iter_enum_5b, (A), (C, D, E)),
114 (C, iter_enum_5c, (A, B), (D, E)),
115 (D, iter_enum_5d, (A, B, C), (E)),
116 (E, iter_enum_5e, (A, B, C, D), ()),
117);
118
119impl_iter_enum!(
120 IterEnum6,
121 IntoIterEnum6,
122 (A, iter_enum_6a, (), (B, C, D, E, F)),
123 (B, iter_enum_6b, (A), (C, D, E, F)),
124 (C, iter_enum_6c, (A, B), (D, E, F)),
125 (D, iter_enum_6d, (A, B, C), (E, F)),
126 (E, iter_enum_6e, (A, B, C, D), (F)),
127 (F, iter_enum_6f, (A, B, C, D, F), ()),
128);
129
130#[cfg(test)]
131mod tests {
132 use core::iter::{empty, once};
133
134 use super::*;
135
136 #[test]
137 fn if_branch() {
138 let eval = |b| {
139 if b {
140 (0..10).iter_enum_2a()
141 } else {
142 (0..10).filter(|i| i % 2 == 0).iter_enum_2b()
143 }
144 .count()
145 };
146
147 assert!(eval(true) == 10);
148 assert!(eval(false) == 5);
149 }
150
151 #[test]
152 fn match_branch() {
153 let eval = |i| {
154 match i {
155 0 => (0..1).iter_enum_3a(),
156 1 => (0..3).iter_enum_3b(),
157 _ => (0..4).iter_enum_3c(),
158 }
159 .count()
160 };
161
162 assert!(eval(0) == 1);
163 assert!(eval(1) == 3);
164 assert!(eval(42) == 4);
165 }
166
167 #[test]
168 fn iterator_of_iterators() {
169 assert!(
170 empty()
171 .chain(once((0..1).iter_enum_3a()))
172 .chain(once((0..2).map(|i| i - 1).iter_enum_3b()))
173 .chain(once((0..3).filter(|i| i % 2 == 0).iter_enum_3c()))
174 .fold(0, |sum, it| sum + it.sum::<i32>())
175 == 1
176 );
177 }
178}