1#![deny(missing_docs)]
6#![deny(warnings)]
7
8#[macro_export]
9macro_rules! pipe_fun {
10 (&, $ret:expr) => {
11 &$ret;
12 };
13 ((as $typ:ty), $ret:expr) => {
14 $ret as $typ;
15 };
16 ({$fun:expr}, $ret:expr) => {
17 $fun($ret);
18 };
19 ([$fun:ident], $ret:expr) => {
20 $ret.$fun();
21 };
22 (($fun:ident($($arg:expr),*)), $ret:expr) => {
23 $fun($ret $(,$arg)*);
24 };
25 ($fun:ident, $ret:expr) => {
26 $fun($ret);
27 }
28}
29
30#[macro_export]
31macro_rules! pipe {
32 ( $expr:expr => $($funs:tt)=>+ ) => {
33 {
34 let ret = $expr;
35 $(
36 let ret = pipe_fun!($funs, ret);
37 )*
38 ret
39 }
40 };
41}
42
43#[macro_export]
44macro_rules! pipe_res {
45 ( $expr:expr => $($funs:tt)=>+ ) => {
46 {
47 let ret = Ok($expr);
48 $(
49 let ret = match ret {
50 Ok(x) => pipe_fun!($funs, x),
51 _ => ret
52 };
53 )*
54 ret
55 }
56 };
57}
58
59#[macro_export]
60macro_rules! pipe_opt {
61 ( $expr:expr => $($funs:tt)=>+ ) => {
62 {
63 let ret = None;
64 $(
65 let ret = match ret {
66 None => pipe_fun!($funs, $expr),
67 _ => ret
68 };
69 )*
70 ret
71 }
72 };
73}
74
75#[cfg(test)]
76mod test_pipe_opt{
77 fn times2(a: u32) -> Option<u32>{
78 return Some(a * 2);
79 }
80
81 fn nope(_a: u32) -> Option<u32>{
82 return None;
83 }
84
85 #[test]
86 fn accepts_options() {
87 let ret = pipe_opt!(
88 4
89 => times2
90 );
91
92 assert_eq!(ret, Some(8));
93 }
94
95 #[test]
96 fn accepts_unwrap() {
97 let ret = pipe_opt!(
98 4
99 => times2
100 ).unwrap();
101
102 assert_eq!(ret, 8);
103 }
104
105
106 #[test]
107 fn exits_early() {
108 let ret = pipe_opt!(
109 4
110 => times2
111 => times2
112 => times2
113 );
114
115 assert_eq!(ret, Some(8));
116 }
117
118 #[test]
119 fn goes_until_some() {
120 let ret = pipe_opt!(
121 4
122 => nope
123 => nope
124 => {|_i: u32| None}
125 => times2
126 => nope
127 );
128
129 assert_eq!(ret, Some(8));
130 }
131
132 #[test]
133 fn ends_with_none() {
134 let ret = pipe_opt!(
135 4
136 => nope
137 => nope
138 => {|_i: u32| None}
139 => nope
140 );
141
142 assert_eq!(ret, None);
143 }
144}
145
146
147#[cfg(test)]
148mod test_pipe_res{
149 fn times2(a: u32) -> Result<u32, String>{
150 return Ok(a * 2);
151 }
152
153 fn fail_if_over_4(a: u32) -> Result<u32, String>{
154 if a > 4 {
155 return Err("This number is larger than four".to_string());
156 }
157 return Ok(a);
158 }
159
160 #[test]
161 fn accepts_results() {
162 let ret = pipe_res!(
163 4
164 => times2
165 );
166
167 assert_eq!(ret, Ok(8));
168 }
169
170 #[test]
171 fn accepts_unwrap() {
172 let ret = pipe_res!(
173 4
174 => times2
175 ).unwrap();
176
177 assert_eq!(ret, 8);
178 }
179
180
181 #[test]
182 fn chains_result_values() {
183 let ret = pipe_res!(
184 4
185 => times2
186 => times2
187 => times2
188 );
189
190 assert_eq!(ret, Ok(32));
191 }
192
193 #[test]
194 fn exits_early() {
195 let ret = pipe_res!(
196 4
197 => times2
198 => fail_if_over_4
199 => times2
200 => times2
201 );
202
203 assert_eq!(ret, Err("This number is larger than four".to_string()));
204 }
205}
206
207#[cfg(test)]
208mod test_pipe{
209 fn times2(a: u32) -> u32{
210 return a * 2;
211 }
212
213 fn times(a: u32, b: u32, c: u32) -> u32{
214 return a * b * c;
215 }
216
217 #[test]
218 fn test_int() {
219 let multiply = |i: u32| i * 2;
220 let ret = pipe!(
221 4
222 => times2
223 => {|i: u32| i * 2}
224 => multiply
225 => (times(100, 10))
226 );
227
228 assert_eq!(ret, 32000);
229 }
230
231 #[test]
232 fn test_string() {
233 let ret = pipe!(
234 "abcd"
235 => [len]
236 => (as u32)
237 => times2
238 => (times(100, 10))
239 => [to_string]
240 );
241
242 assert_eq!(ret, times(times2(("abcd".len() as u32)), 100, 10).to_string());
250 assert_eq!(ret, "8000");
251 }
252}
253