1#![no_std]
2
3pub trait TuplePrepend<T> {
45 type ResultType;
46 fn prepend(self, t: T) -> Self::ResultType;
47}
48
49impl<T> TuplePrepend<T> for () {
50 type ResultType = (T,);
51 #[inline]
52 fn prepend(self, t: T) -> Self::ResultType {
53 (t,)
54 }
55}
56
57macro_rules! _impl_tuple_prepend {
58 ( () ) => {};
59 ( ($t:ident $( $typ:ident)* ) ) => {
60 impl<$t, $($typ,)* TT> TuplePrepend<TT> for ($t, $($typ,)*) {
61 type ResultType = (TT, $t, $($typ),*);
62 #[inline]
63 fn prepend(self, t: TT) -> Self::ResultType {
64 #[allow(non_snake_case)]
65 let ($t, $($typ,)*) = self;
66 (t, $t, $($typ,)*)
67
68 }
69
70 }
71 _impl_tuple_prepend!(($($typ)*));
72
73 }
74
75}
76_impl_tuple_prepend!((
77 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
78));
79
80#[macro_export]
82macro_rules! cartesian {
83 ($head:expr $(,)?) => {
84 $head.into_iter()
85 };
86
87 ($head:expr, $tail:expr $(,)?) => {
91 cartesian!(@ $head.into_iter(), $tail.into_iter())
92 };
93
94 ($head:expr $(, $tail:expr)+ $(,)?) => {
101 cartesian!(@ $head.into_iter(), cartesian!($($tail),+)).map(
102 |(head, tail)| $crate::TuplePrepend::prepend(tail, head)
103 )
104 };
105
106 (@ $head:expr, $tail:expr $(,)?) => {
107 $head.flat_map(|h| $tail.map(move |t| (h, t)))
108 };
109}
110
111#[cfg(test)]
112extern crate alloc;
113#[cfg(test)]
114use alloc::{format, string::String, vec};
115
116#[test]
117fn two_combination() {
118 let mut acc = String::new();
119
120 for (a, b) in cartesian!(0..2, "xy".chars()) {
121 acc += &format!("{}{} ", a, b);
122 }
123
124 assert_eq!(acc, "0x 0y 1x 1y ");
125}
126
127#[test]
128fn binary_numbers() {
129 let mut acc = String::new();
130
131 let range = 0..2;
132 let vec = vec![0, 1];
133 let string = vec![String::from("0"), String::from("1")];
134
135 for (a, b, c) in cartesian!(range, vec.iter(), string.iter()) {
136 acc += &format!("{}{}{} ", a, b, c);
137 }
138
139 assert_eq!(acc, "000 001 010 011 100 101 110 111 ");
140}
141
142#[test]
143fn trailing_commas() {
144 let mut acc = String::new();
145
146 for a in cartesian!(
147 0..1,
148 ) {
149 acc += &format!("{} ", a);
150 }
151
152 for (a, b) in cartesian!(
153 0..2,
154 0..2,
155 ) {
156 acc += &format!("{}{} ", a, b);
157 }
158
159 for (a, b, c) in cartesian!(
160 0..2,
161 0..2,
162 0..2,
163 ) {
164 acc += &format!("{}{}{} ", a, b, c);
165 }
166
167 assert_eq!(acc, "0 00 01 10 11 000 001 010 011 100 101 110 111 ");
168}
169
170#[test]
171fn by_reference() {
172 let mut acc = String::new();
173
174 let outer = vec![String::from("a"), String::from("b")];
175 let inner = vec![String::from("0"), String::from("1")];
176
177 for (a, b) in cartesian!(&outer, &inner) {
178 acc += &format!("{}{} ", a, b);
179 }
180
181 assert_eq!(acc, "a0 a1 b0 b1 ");
182}