1#![no_std]
15
16#[macro_export]
17macro_rules! pipe {
18 (@finish $x:expr, -> $($xs:tt)+) => {
19 $crate::pipe!(@start $x, [], $($xs)+)
20 };
21 (@finish $x:expr, => $($xs:tt)+) => {
22 $crate::pipe!(@start2 $x, [], [], $($xs)+)
23 };
24 (@finish $x:expr,) => {
25 $x
26 };
27 (@call ($($x:expr),+), [$($f:tt)+], ($($y:expr),*$(,)?). $($xs:tt)*) => {
28 $crate::pipe!(@call ($($x),+), [$($f)+($($y),*).], $($xs)*)
29 };
30 (@call ($($x:expr),+), [$($f:tt)+], ($($y:expr),*$(,)?)? $($xs:tt)*) => {
31 $crate::pipe!(@call ($($x),+), [$($f)+($($y),*)?], $($xs)*)
32 };
33 (@call ($($x:expr),+), [$($f:tt)+], ($($y:expr),+$(,)?)($($z:expr),+$(,)?) $($xs:tt)*) => {
34 $crate::pipe!(@call ($($y,)+ $($x),+), [$($f)+], ($($z),+) $($xs)*)
35 };
36 (@call ($($x:expr),+), [$($f:tt)+], ($($y:expr),+$(,)?) $($xs:tt)*) => {
37 $crate::pipe!(@finish $($f)+($($y,)+ $($x),+), $($xs)*)
38 };
39 (@call ($($x:expr),+), [$($f:tt)+], -> $($xs:tt)*) => {
40 $crate::pipe!(@start $($f)+($($x),+), [], $($xs)+)
41 };
42 (@call ($($x:expr),+), [$($f:tt)+], => $($xs:tt)*) => {
43 $crate::pipe!(@start2 $($f)+($($x),+), [], [], $($xs)+)
44 };
45 (@call ($($x:expr),+), [$($f:tt)+],) => {
46 $($f)+($($x),+)
47 };
48 (@call ($($x:expr),+), [$($f:tt)+], $y:tt $($xs:tt)*) => {
49 $crate::pipe!(@call ($($x),+), [$($f)+$y], $($xs)*)
50 };
51 (@method $x:expr, [$($f:tt)+]($($y:expr),*), [$($z:expr),*], ::<$($t:ty),+$(,)?> $($xs:tt)*) => {
52 $crate::pipe!(@method $x, [$($f)+::<$($t),+>]($($y,)*), [$($z),*], $($xs)*)
53 };
54 (
55 @method $x:expr,
56 [$($f:tt)+]($($y:expr),*),
57 [$($z:expr),*],
58 ($($zz:expr),+$(,)?) $($xs:tt)*) =>
59 {
60 $crate::pipe!(@method $x, [$($f)+]($($y,)* $($zz),+), [$($z),*], $($xs)*)
61 };
62 (@method $x:expr, [$($f:tt)+]($($y:expr),*), [$($z:expr),*], $($xs:tt)*) => {
63 $crate::pipe!(@finish ($x).$($f)+($($y,)*$($z),*), $($xs)*)
64 };
65 (@start $x:expr, [$($u:tt)*], &mut $($xs:tt)*) => {
66 $crate::pipe!(@start $x, [$($u)* &mut], $($xs)*)
67 };
68 (@start $x:expr, [$($u:tt)*], && $($xs:tt)*) => {
69 $crate::pipe!(@start $x, [$($u)* &&], $($xs)*)
70 };
71 (@start $x:expr, [$($u:tt)*], & $($xs:tt)*) => {
72 $crate::pipe!(@start $x, [$($u)* &], $($xs)*)
73 };
74 (@start $x:expr, [$($u:tt)*], * $($xs:tt)*) => {
75 $crate::pipe!(@start $x, [$($u)* *], $($xs)*)
76 };
77 (@start $x:expr, [$($u:tt)*], await $($xs:tt)*) => {
78 $crate::pipe!(@start ($x).await, [$($u)*], $($xs)*)
79 };
80 (@start $x:expr, [$($u:tt)*], ? $($xs:tt)*) => {
81 $crate::pipe!(@start ($x)?, [$($u)*], $($xs)*)
82 };
83 (@start $x:expr, [$($u:tt)*], -> $($xs:tt)+) => {
84 $crate::pipe!(@start $($u)*($x), [], $($xs)+)
85 };
86 (@start $x:expr, [$($u:tt)*], => $($xs:tt)+) => {
87 $crate::pipe!(@start2 $($u)*($x), [], [], $($xs)+)
88 };
89 (@start $x:expr, [$($u:tt)*], match $c:tt $($xs:tt)*) => {
90 $crate::pipe!(@finish match $($u)*($x) $c, $($xs)*)
91 };
92 (@start $x:expr, [$($u:tt)*], if $t:block else $f:block $($xs:tt)*) => {
93 $crate::pipe!(@finish if $($u)*($x) $t else $f, $($xs)*)
94 };
95 (@start $x:expr, [$($u:tt)*], $f:ident $($xs:tt)*) => {
96 $crate::pipe!(@call ($($u)*($x)), [$f], $($xs)*)
97 };
98 (@start $x:expr, [$($u:tt)*], .$f:ident $($xs:tt)*) => {
99 $crate::pipe!(@method $($u)*($x), [$f](), [], $($xs)*)
100 };
101 (@start $x:expr, [$($u:tt)*], [.$($p:tt)+] $($xs:tt)*) => {
102 $crate::pipe!(@finish ($($u)*($x)).$($p)+, $($xs)*)
103 };
104 (@start $x:expr, [$($u:tt)*], [$i:expr] $($xs:tt)*) => {
105 $crate::pipe!(@finish ($($u)*($x))[$i], $($xs)*)
106 };
107 (@start $x:expr, [$($u:tt)*], _) => {{
108 let _ = $($u)*($x);
109 }};
110 (@start $x:expr, [$($u:tt)*], |$y:pat_param| $e:block $($xs:tt)*) => {
111 $crate::pipe!(@finish (|$y| $e)($($u)*($x)), $($xs)*)
112 };
113 (@start $x:expr, [$($u:tt)*],) => {
114 $($u)*($x)
115 };
116 (@start2 $x:expr, [$($u:tt)*], [$($s:tt)*], &mut $($xs:tt)*) => {
117 $crate::pipe!(@start2 $x, [$($u)* &mut], [$($s)*], $($xs)*)
118 };
119 (@start2 $x:expr, [$($u:tt)*], [$($s:tt)*], && $($xs:tt)*) => {
120 $crate::pipe!(@start2 $x, [$($u)* &&], [$($s)*], $($xs)*)
121 };
122 (@start2 $x:expr, [$($u:tt)*], [$($s:tt)*], & $($xs:tt)*) => {
123 $crate::pipe!(@start2 $x, [$($u)* &], [$($s)*], $($xs)*)
124 };
125 (@start2 $x:expr, [$($u:tt)*], [$($s:tt)*], * $($xs:tt)*) => {
126 $crate::pipe!(@start2 $x, [$($u)* *], [$($s)*], $($xs)*)
127 };
128 (@start2 $x:expr, [$($u:tt)*], [$($s:tt)*], await $($xs:tt)*) => {
129 $crate::pipe!(@start2 $x, [$($u)*], [$($s)*.await], $($xs)*)
130 };
131 (@start2 $x:expr, [$($u:tt)*], [$($s:tt)*], ? $($xs:tt)*) => {
132 $crate::pipe!(@start2 $x, [$($u)*], [$($s)*?], $($xs)*)
133 };
134 (@start2 $x:expr, [$($u:tt)*], [$($s:tt)*], -> $($xs:tt)+) => {{
135 #[allow(unused_mut)]
136 let mut x = $x;
137 $crate::pipe!(@start ($($u)*x.0$($s)*, $($u)*x.1$($s)*), [], $($xs)+)
138 }};
139 (@start2 $x:expr, [$($u:tt)*], [$($s:tt)*], => $($xs:tt)+) => {{
140 #[allow(unused_mut)]
141 let mut x = $x;
142 $crate::pipe!(@start2 ($($u)*x.0$($s)*, $($u)*x.1$($s)*), [], [], $($xs)+)
143 }};
144 (@start2 $x:expr, [$($u:tt)*], [$($s:tt)*], match $c:tt $($xs:tt)*) => {{
145 #[allow(unused_mut)]
146 let mut x = $x;
147 $crate::pipe!(@finish match ($($u)*x.0$($s)*, $($u)*x.1$($s)*) $c, $($xs)*)
148 }};
149 (@start2 $x:expr, [$($u:tt)*], [$($s:tt)*], $f:ident $($xs:tt)*) => {{
150 #[allow(unused_mut)]
151 let mut x = $x;
152 $crate::pipe!(@call ($($u)*x.0$($s)*, $($u)*x.1$($s)*), [$f], $($xs)*)
153 }};
154 (
155 @start2 $x:expr,
156 [$($u:tt)*],
157 [$($s:tt)*],
158 |$y:pat_param, $z:pat_param| $e:block $($xs:tt)*) =>
159 {{
160 #[allow(unused_mut)]
161 let mut x = $x;
162 $crate::pipe!(@finish (|$y, $z| $e)($($u)*x.0$($s)*, $($u)*x.1$($s)*), $($xs)*)
163 }};
164 (@start2 $x:expr, [$($u:tt)*], [$($s:tt)*],) => {{
165 #[allow(unused_mut)]
166 let mut x = $x;
167 ($($u)*x.0$($s)*, $($u)*x.1$($s)*)
168 }};
169 (@init [$($x:tt)+], -> $($xs:tt)+) => {
170 $crate::pipe!(@start $($x)+, [], $($xs)+)
171 };
172 (@init [$($x:tt)+], => $($xs:tt)+) => {
173 $crate::pipe!(@start2 $($x)+, [], [], $($xs)+)
174 };
175 (@init [$($x:tt)+], $x1:tt $($xs:tt)*) => {
176 $crate::pipe!(@init [$($x)+$x1], $($xs)*)
177 };
178 (@init [$x:expr],) => {
179 $x
180 };
181 (@$($xs:tt)*) => {
182 compile_error!("Failed to match rule")
183 };
184 ($x:tt $($xs:tt)*) => {
185 $crate::pipe!(@init [$x], $($xs)*)
186 };
187}
188
189#[cfg(test)]
190mod tests {
191 mod foo {
192 pub fn ident<T>(x: T) -> T {
193 x
194 }
195
196 pub fn second<T>(_: T, x: T) -> T {
197 x
198 }
199
200 pub fn third<T>(_: T, _: T, x: T) -> T {
201 x
202 }
203 }
204
205 mod bar {
206 pub fn wrap<T>(x: T) -> Option<T> {
207 Some(x)
208 }
209
210 pub fn wrap2<T>(x: T, y: T) -> (Option<T>, Option<T>) {
211 (Some(x), Some(y))
212 }
213 }
214
215 use bar::*;
216 use foo::*;
217
218 #[test]
219 fn r#ref() {
220 assert_eq!(&0, pipe!(0 -> & -> ident));
221 assert_eq!(&0, pipe!(0 -> &ident));
222 assert_eq!(&mut 0, pipe!(0 -> &mut -> foo::ident));
223 assert_eq!(&mut 0, pipe!(0 -> &mut foo::ident::<&mut u32>));
224 assert_eq!(0, pipe!(0 -> & -> second(&1) -> *));
225 assert_eq!(0, pipe!(0 -> &&second(&&1) -> **));
226 assert_eq!(0, pipe!(0 -> &mut -> foo::third(&mut 1, &mut 2) -> *));
227 assert_eq!(0, pipe!(0 -> &mut foo::third(&mut 1)(&mut 2) -> *));
228
229 assert_eq!(1, pipe!((0, 1) => & => second -> *));
230 assert_eq!(1, pipe!((0, 1) => &second -> *));
231 assert_eq!(1, pipe!((0, 1) => &mut => second -> *));
232 assert_eq!(1, pipe!((0, 1) => &mut second -> *));
233 assert_eq!(1, pipe!((0, 1) => && => second -> **));
234 assert_eq!(1, pipe!((0, 1) => &&second -> **));
235 assert_eq!(1, pipe!((0, 1) => &third(&2) -> *));
236 }
237
238 #[test]
239 fn r#try() {
240 fn inner() -> Option<()> {
241 assert_eq!(0, pipe!(Some(0) -> ? -> ident));
242 assert_eq!(0, pipe!(Some(0) -> ?foo::ident));
243 assert_eq!(0, pipe!(0 -> wrap -> ?));
244 assert_eq!(0, pipe!(Some(0) -> bar::wrap -> ? -> ?));
245 assert_eq!(0, pipe!(Some(0) -> bar::wrap -> ??));
246 assert_eq!((0, 1), pipe!((0, 1) => wrap2 => ?));
247 assert_eq!((0, 1), pipe!((0, 1) => bar::wrap2 => ?));
248 assert_eq!((0, 1), pipe!((Some(0), Some(1)) => ?wrap2 => ?));
249 assert_eq!((0, 1), pipe!((Some(0), Some(1)) => ?bar::wrap2 => ?));
250 pipe!(None::<()> -> bar::wrap -> ??);
251 unreachable!();
252 }
253 inner();
254 }
255
256 #[test]
257 fn method() {
258 #[derive(Debug, PartialEq, Eq)]
259 struct U32(u32);
260
261 impl U32 {
262 fn incr(self) -> U32 {
263 U32(self.0 + 1)
264 }
265
266 fn add2(&self, b: u32) -> U32 {
267 U32(self.0 + b)
268 }
269
270 fn add3(&mut self, b: u32, c: u32) -> U32 {
271 U32(self.0 + b + c)
272 }
273
274 fn add4(&mut self, b: u32, c: u32, d: u32) -> U32 {
275 U32(self.0 + b + c + d)
276 }
277
278 fn add_assign(&mut self, b: u32) -> U32 {
279 self.0 += b;
280 U32(self.0)
281 }
282
283 fn konst<T>(&self, x: T) -> T {
284 x
285 }
286 }
287
288 let mut x = U32(0);
289 assert_eq!(U32(1), pipe!(U32(0) -> .incr));
290 assert_eq!(U32(1), pipe!(U32(0) -> .add2(1)));
291 assert_eq!(U32(2), pipe!(U32(0) -> &.add2(1) -> .incr));
292 assert_eq!(U32(3), pipe!(U32(0) -> .add3(1, 2)));
293 assert_eq!(U32(4), pipe!(U32(0) -> &mut .add3(1, 2) -> .incr));
294 assert_eq!(U32(5), pipe!(5 -> x.add_assign));
295 assert_eq!(U32(6), pipe!(0 -> x.add3(1)));
296 assert_eq!(U32(7), pipe!(U32(0) -> .konst::<_>(U32(7))));
297 assert_eq!(U32(8), pipe!((1, 2) => x.add3));
298 assert_eq!(U32(9), pipe!((0, 1) => x.add4(3)));
299 }
300
301 #[test]
302 fn index() {
303 let xs = [0, 1, 2];
304 assert_eq!(0, pipe!(xs -> [0]));
305 assert_eq!(1, pipe!(&xs -> [1]));
306 assert_eq!(2, pipe!(xs -> &[1 + 1]));
307 assert_eq!(3, pipe!(xs -> &[2] -> |x| { x + 1 }));
308 }
309
310 #[test]
311 fn access() {
312 struct Foo(u32, u32);
313
314 struct Bar {
315 a: u32,
316 b: Foo,
317 }
318
319 let x = (0, 1);
320 let y = Foo(2, 3);
321 let z = Bar { a: 4, b: Foo(5, 6) };
322 assert_eq!(0, pipe!(x -> [.0]));
323 assert_eq!(1, pipe!(x -> &[.1]));
324 assert_eq!(2, pipe!(&y -> [.0]));
325 assert_eq!(3, pipe!(&y -> [.1]));
326 assert_eq!(4, pipe!(&z -> [.a]));
327 assert_eq!(5, pipe!(z -> &[.b] -> [.0]));
328 assert_eq!(6, pipe!(&z -> &[.b.1]));
329 }
330
331 #[test]
332 fn sink() {
333 assert_eq!((), pipe!(0 -> _));
334 }
335
336 #[test]
337 fn r#match() {
338 assert_eq!(0, pipe!(false -> match { false => 0, true => 1}));
339 assert_eq!(
340 1,
341 pipe!(false
342 -> match { false => true, true => false}
343 -> *&match { false => 0, true => 1}),
344 );
345 assert_eq!((1, 2), pipe!((0, 1) => &match { (x, y) => (*x + 1, *y + 1) }));
346 }
347
348 #[test]
349 fn r#if() {
350 assert_eq!(0, pipe!(false -> if { 1 } else { 0 }));
351 assert_eq!(
352 1,
353 pipe!(false
354 -> if { false } else { true }
355 -> *&if { 1 } else { 0 }),
356 );
357 }
358
359 #[test]
360 fn closure() {
361 assert_eq!(1, pipe!(0 -> |x| { x + 1 }));
362 assert_eq!(
363 2,
364 pipe!(0 -> |x| {
365 let x = x + 1;
366 x + 1
367 }),
368 );
369 assert_eq!(
370 3,
371 pipe!(0
372 -> |x| {
373 let x = x + 1;
374 x + 1
375 }
376 -> |x| { x + 1 }),
377 );
378 assert_eq!(4, pipe!((0, 1) -> |(x, y)| { (x + 1, y + 1) } => |x, y| { x + y + 1 }));
379 }
380
381 #[test]
382 fn combo() {
383 struct Foo(Option<u32>);
384
385 impl Foo {
386 fn new(x: Option<u32>) -> Self {
387 Self(x)
388 }
389
390 fn wrap(&self) -> Option<Option<u32>> {
391 Some(self.0)
392 }
393
394 fn wrap_add(&self, x: u32) -> Option<Option<u32>> {
395 Some(self.0.map(|y| y + x))
396 }
397 }
398
399 fn inner() -> Option<()> {
400 assert_eq!(0, pipe!(Some(0) -> *&?bar::wrap -> ?));
401 assert_eq!(0, pipe!(Some(Some(Foo(Some(0)))) -> ?&&&*&&&*&?.wrap -> ??));
402 assert_eq!(1, pipe!(Some(0) -> ?Foo::new(Some(1)).wrap_add -> ??));
403 Some(())
404 }
405 inner();
406 }
407
408 #[test]
409 fn pointless() {
410 assert_eq!(0, pipe!(0 -> pipe! -> pipe!));
411 }
412}