1#[doc(hidden)]
10#[macro_export]
11macro_rules! em_if {
12 ( $i:expr, $p:pat, $t:expr, $f:expr ) => {
13 if let $p = $i {
14 $t
15 } else {
16 $f
17 }
18 };
19}
20
21#[doc(hidden)]
22#[macro_export]
23macro_rules! get {
24 ( $i:expr, $p:path, $pp:tt, $r:expr ) => {
25 $crate::em_if!($i, $p$pp, Some($r), None)
26 };
27 ( $i:expr, $p:path ) => {
28 $crate::em_if!($i, $p, Some(()), None)
29 };
30}
31
32#[doc(hidden)]
33#[macro_export]
34macro_rules! is {
35 ( $i:expr, $p:path, $pp:tt, $r:expr ) => {
36 $crate::em_if!($i, $p$pp, true, false)
37 };
38 ( $i:expr, $p:path ) => {
39 $crate::em_if!($i, $p, true, false)
40 };
41}
42
43#[doc(hidden)]
44#[macro_export]
45macro_rules! map {
46 ( $i:ident, $p:path, $pp:tt, $r:expr, $f:expr ) => {
47 $crate::em_if!($i, $p$pp, $p($f($r)), $i)
48 };
49}
50
51#[doc(hidden)]
52#[macro_export]
53macro_rules! and_then {
54 ( $i:ident, $p:path, $pp:tt, ($($r:ident,)+), $f:expr ) => {
55 $crate::em_if!($i, $p$pp, $f($($r,)+), $i)
56 };
57 ( $i:ident, $p:path, $pp:tt, $r:ident, $f:expr ) => {
58 $crate::em_if!($i, $p$pp, $f($r), $i)
59 };
60}
61
62#[macro_export]
132macro_rules! em {
133 ( $i:ident.$m:ident $p:path $(> $($a:expr),+)? ) => {
134 $crate::$m!($i, $p, (_x), _x $(, $($a),+)?)
135 };
136 ( $i:ident.$m:ident $p:path[$(..)?] $(> $($a:expr),+)? ) => {
137 $crate::$m!($i, $p, (..), () $(, $($a),+)?)
138 };
139 ( $i:ident.$m:ident $p:path[$($x:ident),+] $(> $($a:expr),+)? ) => {
140 $crate::$m!($i, $p, ($($x,)+), ($($x,)+) $(, $($a),+)?)
141 };
142 ( $i:ident.$m:ident $p:path{$($($x:ident),+$(,)?)? $(..)?} $(> $($a:expr),+)? ) => {
143 $crate::$m!($i, $p, { $($($x,)+)? .. }, ($($($x,)+)?) $(, $($a),+)?)
144 };
145 ( $i:expr => $m:ident $p:path $(> $($a:expr),+)? ) => {
146 $crate::$m!($i, $p, (_x), _x $(, $($a),+)?)
147 };
148 ( $i:expr => $m:ident $p:path[$(..)?] $(> $($a:expr),+)? ) => {
149 $crate::$m!($i, $p, (..), () $(, $($a),+)?)
150 };
151 ( $i:expr => $m:ident $p:path[$($x:ident),+] $(> $($a:expr),+)? ) => {
152 $crate::$m!($i, $p, ($($x,)+), ($($x,)+) $(, $($a),+)?)
153 };
154 ( $i:expr => $m:ident $p:path{$($($x:ident),+$(,)?)? $(..)?} $(> $($a:expr),+)? ) => {
155 $crate::$m!($i, $p, { $($($x,)+)? .. }, ($($($x,)+)?) $(, $($a),+)?)
156 };
157 ( $i:ident.$m:ident $p:path| $(> $($a:expr),+)? ) => {
158 $crate::$m!($i, $p $(, $($a),+)?)
159 };
160 ( $i:expr => $m:ident $p:path| $(> $($a:expr),+)? ) => {
161 $crate::$m!($i, $p $(, $($a),+)?)
162 };
163}
164
165#[cfg(test)]
166mod tests {
167 #[derive(Debug, PartialEq)]
168 enum Enum {
169 A(i32),
170 B(i32, i32),
171 C { x: i32, y: i32 },
172 D,
173 }
174
175 fn init() -> (Enum, Enum, Enum) {
176 let a = Enum::A(1);
177 let b = Enum::B(2, 3);
178 let c = Enum::C { x: 4, y: 5 };
179 (a, b, c)
180 }
181
182 #[test]
183 fn get() {
184 let (a, b, c) = init();
185 let d = Enum::D;
186 assert_eq!(em!(a.get Enum::A), Some(1));
187 assert_eq!(em!(Enum::A(1) => get Enum::A), Some(1));
188 assert_eq!(em!(b.get Enum::B[i, j]), Some((2, 3)));
189 assert_eq!(em!(c.get Enum::C{x, y}), Some((4, 5)));
190 assert_eq!(em!(c.get Enum::C{x, ..}), Some((4,)));
191 assert_eq!(em!(d.get Enum::D|), Some(()));
192 assert_eq!(em!(Enum::D => get Enum::D|), Some(()));
193 }
194
195 #[test]
196 fn not_get() {
197 let (a, b, c) = init();
198 assert_eq!(em!(a.get Enum::C{x, y}), None);
199 assert_eq!(em!(b.get Enum::A), None);
200 assert_eq!(em!(c.get Enum::B[i, j]), None);
201 assert_eq!(em!(Enum::A(1) => get Enum::D|), None);
202 }
203
204 #[test]
205 fn is() {
206 let (a, b, c) = init();
207 let d = Enum::D;
208 assert_eq!(em!(a.is Enum::A), true);
209 assert_eq!(em!(b.is Enum::B[]), true);
210 assert_eq!(em!(c.is Enum::C{}), true);
211 assert_eq!(em!(d.is Enum::D|), true);
212 }
213
214 #[test]
215 fn isnt() {
216 let (a, b, c) = init();
217 let d = Enum::D;
218 assert_eq!(em!(a.is Enum::D|), false);
219 assert_eq!(em!(b.is Enum::A), false);
220 assert_eq!(em!(c.is Enum::B[]), false);
221 assert_eq!(em!(d.is Enum::C{}), false);
222 }
223
224 #[test]
225 fn map() {
226 let (a, b, _c) = init();
227 assert_eq!(em!(a.map Enum::A > |x| x + 1), Enum::A(2));
228 assert_eq!(em!(b.map Enum::A > |x| x + 1), Enum::B(2, 3));
229 }
230
231 #[test]
232 fn and_then() {
233 let (a, b, c) = init();
234 assert_eq!(
235 em!(a.and_then Enum::A > |x| Enum::B(x + 1, 0)),
236 Enum::B(2, 0)
237 );
238 assert_eq!(
239 em!(b.and_then Enum::B[x, y] > |x, y| Enum::C {x, y}),
240 Enum::C { x: 2, y: 3 }
241 );
242 assert_eq!(
243 em!(c.and_then Enum::A > |x| Enum::B(x - 1, 0)),
244 Enum::C { x: 4, y: 5 }
245 );
246 }
247}