1#![cfg_attr(test, feature(macro_metavar_expr))]
2#![no_std]
3#![doc = include_str!("../README.md")]
4
5#[macro_export]
15macro_rules! pipe {
16 ($e:expr) => { $e };
17 ($in:expr => $($i:ident).+ $(())? $(=> $($tail:tt)+)?) => {
18 pipe!($($i).+($in) $(=> $($tail)+)?)
19 };
20 ($in:expr => $($i:ident).+ ($($($arg_head:expr_2021),*,)? $(_ $(, $arg_tail:expr_2021)*),*) $(=> $($tail:tt)+)?) => {
21 {
22 let pipe_temp = $in; pipe!($($i).+($($($arg_head),*,)? $(pipe_temp $(, $arg_tail)*),*) $(=> $($tail)+)?)
24 }
25 };
26 ($in:expr => ($e:expr) ($($($arg_head:expr_2021),*,)? $(_ $(, $arg_tail:expr_2021)*),*) $(=> $($tail:tt)+)?) => {
27 {
28 let pipe_temp = $in; pipe!($e($($($arg_head),*,)? $(pipe_temp $(, $arg_tail)*),*) $(=> $($tail)+)?)
30 }
31 };
32 ($in:expr => $e:expr $(=> $($tail:tt)+)?) => {
33 pipe!($e($in) $(=> $($tail)+)?)
34 };
35}
36
37#[cfg(test)]
38mod tests {
39 #[test]
41 fn test_simple() {
42 fn test(x: u16) -> f32 {
43 f32::from(x + 1)
44 }
45
46 fn test2(x: f32) -> f32 {
47 x + 1.
48 }
49
50 let x = 3;
51
52 assert_eq!(pipe!(x+1 => test => test2), test2(test(x + 1)));
53 assert_eq!(pipe!(x+1 => test() => test2()), test2(test(x + 1)));
54 }
55
56 #[test]
58 fn test_underscore_fill() {
59 fn test(x: u16) -> u16 {
60 x
61 }
62 fn test2(x: u16, y: u16) -> (u16, u16) {
63 (x, y)
64 }
65
66 let x = 3;
67 let y = 4;
68
69 assert_eq!(pipe!(x-1 => test => test2(_, y)), test2(test(x - 1), y));
70 assert_eq!(pipe!(x-1 => test => test2(y, _)), test2(y, test(x - 1),));
71 assert_eq!(
72 pipe!(x-1 => test => test2(_, _)),
73 test2(test(x - 1), test(x - 1))
74 );
75 }
76
77 #[test]
79 fn test_associated_functions() {
80 fn test(x: u16) -> u16 {
81 x + 1
82 }
83
84 let x = 3;
85
86 assert_eq!(
87 pipe!(x-2 => test => u16::to_be => u16::isqrt),
88 u16::isqrt(u16::to_be(test(x - 2)))
89 );
90 }
91
92 #[test]
94 fn test_methods() {
95 fn test(x: u16) -> u16 {
96 x + 1
97 }
98
99 let x = 3;
100 let y = 4;
101 assert_eq!(
102 pipe!(x+2 => test => y.max => test),
103 test(y.max(test(x + 2)))
104 );
105
106 let mut y = None;
107 assert_eq!(
108 pipe!(x+2 => y.map_or(_, |x| x + 2) => test),
109 test(y.map_or(x + 2, |x| x + 2))
110 );
111
112 y = Some(x + 2);
113 assert_eq!(
114 pipe!(x+2 => y.map_or(_, |x| x + 2) => test),
115 test(y.map_or(x + 2, |x| x + 2))
116 );
117 }
118
119 #[test]
121 fn test_lambdas() {
122 fn test(x: u16) -> u16 {
123 x + 1
124 }
125
126 let x = 3;
127
128 assert_eq!(
129 pipe!(x => test => |x| {x - 2} => test),
130 test((|x| { x - 2 })(test(x)))
131 );
132 }
133
134 #[test]
136 fn test_macros() {
137 use paste::paste;
138
139 macro_rules! bind {
141 ($($f:ident).+ ($($($head:expr_2021),*,)? $(_ $(, $tail:expr_2021)*),*)) => {
142 paste! {
143 |$([<x ${index()}>] $(${ignore($tail)})*),+| {
144 $($f).+($($($head),*,)? $([<x ${index()}>] $(, $tail)*),*)
145 }
146 }
147 };
148 ($($f:ident).+ ($($head:expr_2021),*)) => {
149 || {
150 $($f).+($($head),*)
151 }
152 };
153 }
154
155 fn test(x: u16, y: u16, z: u16) -> (u16, u16, u16) {
156 (x, y, z)
157 }
158
159 let x = 1;
160 let y = 2;
161 let z = 3;
162
163 assert_eq!(pipe!(x => bind!(test(_, y, z))), test(x, y, z));
164 assert_eq!(pipe!(y => bind!(test(x, _, z))), test(x, y, z));
165 assert_eq!(pipe!(x => (bind!(test(_, _, z))) (_, _)), test(x, x, z));
166 }
167}