1use quote::ToTokens;
7use std::cell::{Ref, RefCell};
8use std::rc::Rc;
9use syn::parse::ParseStream;
10use syn::Expr::Let;
11use syn::{Pat, Token};
12
13use super::*;
14use crate::instant_and_deferred_determiners;
15
16struct ExprChainInternal<Member, GroupDeterminer> {
20 members: Vec<Member>,
21 group_determiners: Vec<GroupDeterminer>,
22 pat: Option<Pat>,
23}
24
25pub struct ExprChain<Member, GroupDeterminer> {
29 inner: Rc<RefCell<ExprChainInternal<Member, GroupDeterminer>>>,
30}
31
32#[derive(Debug, Clone, PartialEq, Eq)]
37pub struct ProcessWithDefault(pub Option<ProcessActionExpr>, pub Option<DefaultActionExpr>);
38
39pub type ExprChainWithDefault = ExprChain<ProcessWithDefault, GroupDeterminer>;
43
44impl Chain for ExprChainWithDefault {
48 type Member = ProcessWithDefault;
49
50 fn new(
51 input: ParseStream,
52 other_pattern_check: Box<dyn Fn(ParseStream<'_>) -> bool>,
53 ) -> syn::Result<Option<ExprChainWithDefault>> {
54 let mut group_determiners = instant_and_deferred_determiners! {
55 Map => Token![|], Token![>]; 2,
56 Then => Token![->]; 2,
57 AndThen => Token![=>]; 2,
58 Or => Token![<], Token![|]; 2,
59 OrElse => Token![<=]; 2,
60 Dot => Token![>], Token![.]; 2,
61 MapErr => Token![!], Token![>]; 2,
62 Inspect => Token![?], Token![>]; 2
63 };
64
65 group_determiners.extend(vec![
66 GroupDeterminer::new(None, other_pattern_check, Some(Box::new(is_valid_expr)), 0),
67 GroupDeterminer::new(
68 None,
69 Box::new(|input| input.peek(Token![,])),
70 Some(Box::new(is_valid_expr)),
71 0,
72 ),
73 ]);
74
75 let inner = Rc::new(RefCell::new(ExprChainInternal {
76 members: Vec::new(),
77 group_determiners,
78 pat: None,
79 }));
80
81 let expr_chain = ExprChain { inner };
82
83 if input.is_empty() {
84 Ok(None)
85 } else {
86 expr_chain.process(input)?;
87 Ok(Some(expr_chain))
88 }
89 }
90
91 fn get_members(&self) -> Ref<'_, Vec<Self::Member>> {
92 Ref::map(RefCell::borrow(&self.inner), |inner| &inner.members)
93 }
94
95 fn get_pat(&self) -> Ref<'_, Option<Pat>> {
96 Ref::map(RefCell::borrow(&self.inner), |inner| &inner.pat)
97 }
98}
99
100impl ExprChainWithDefault {
101 fn parse_unit(&self, input: ParseStream) -> UnitResult {
105 let expr_chain = RefCell::borrow(&self.inner);
106 parse_until(input, &expr_chain.group_determiners[..])
107 }
108
109 fn process(&self, input: ParseStream) -> syn::Result<()> {
113 let mut group_type = Some(ActionGroup::Instant(CommandGroup::Initial));
114 let mut is_block;
115 let mut member_index = 0;
116
117 while {
118 let input = input;
119 let Unit {
120 mut expr,
121 next_group_type,
122 } = self.parse_unit(input)?;
123
124 if member_index == 0 {
125 if let Let(let_expr) = expr {
126 self.inner.borrow_mut().pat = Some(let_expr.pat);
127 expr = *let_expr.expr;
128 }
129 }
130
131 let (default_expr, next_group_type) = match next_group_type {
132 Some(ActionGroup::Instant(CommandGroup::Or))
133 | Some(ActionGroup::Deferred(CommandGroup::Or)) => {
134 let current_group_type = next_group_type.unwrap();
135 let Unit {
136 expr,
137 next_group_type,
138 } = self.parse_unit(input)?;
139 Some((
140 current_group_type.map_to_default_action_expr(expr),
141 next_group_type,
142 ))
143 }
144 Some(ActionGroup::Instant(CommandGroup::OrElse))
145 | Some(ActionGroup::Deferred(CommandGroup::OrElse)) => {
146 let current_group_type = next_group_type.unwrap();
147 let Unit {
148 expr,
149 next_group_type,
150 } = self.parse_unit(input)?;
151 Some((
152 current_group_type.map_to_default_action_expr(expr),
153 next_group_type,
154 ))
155 }
156 _ => None,
157 }
158 .unwrap_or((None, next_group_type));
159
160 let expr = group_type
161 .and_then(|action_group_type| action_group_type.map_to_process_action_expr(expr));
162
163 is_block = default_expr
164 .as_ref()
165 .map_or_else(
166 || expr.as_ref().map(|expr| expr.extract_expr().clone()),
167 |v| Some(v.extract_expr().clone()),
168 )
169 .map(|expr| is_block_expr(&expr))
170 .unwrap_or(false);
171
172 let member = ProcessWithDefault(expr, default_expr);
173
174 if member_index == 0
175 && match &member {
176 ProcessWithDefault(expr, _) => expr
177 .as_ref()
178 .unwrap()
179 .extract_expr()
180 .into_token_stream()
181 .is_empty(),
182 }
183 {
184 return Err(input.error("Chain first member can't be empty"));
185 }
186
187 if member.0.is_some() || member.1.is_some() {
188 self.inner.borrow_mut().members.push(member);
189 }
190
191 member_index += 1;
192
193 group_type = next_group_type;
194
195 group_type.is_some()
196 } {}
197
198 let members = &RefCell::borrow(&self.inner).members;
199
200 if members.is_empty() {
201 Err(input.error("Chain can't be empty"))
202 } else {
203 if is_block {
204 input.parse::<Option<Token![,]>>()?;
205 } else if !input.is_empty() {
206 input.parse::<Token![,]>()?;
207 }
208 Ok(())
209 }
210 }
211}
212
213#[cfg(test)]
214mod tests {
215 use super::super::expr::{DefaultExpr, ProcessExpr};
216 use super::*;
217 use ::quote::quote;
218 use ::syn::parse::Parse;
219
220 impl Parse for ExprChainWithDefault {
221 fn parse(input: ParseStream) -> syn::Result<Self> {
222 ExprChainWithDefault::new(input, Box::new(|_| false))
223 .transpose()
224 .ok_or(input.error("empty"))?
225 }
226 }
227
228 #[test]
229 fn it_parses_chain_from_3_process_expr() {
230 let chain =
231 ::syn::parse2::<ExprChainWithDefault>(quote! { Ok(2) => |v| Ok(v + 1) |> |v| v + 2 })
232 .unwrap();
233 assert_eq!(chain.get_members().len(), 3);
234 assert!(chain.get_pat().is_none());
235 }
236
237 #[test]
238 fn it_parses_chain_from_3_process_expr_and_1_default_expr() {
239 let chain = ::syn::parse2::<ExprChainWithDefault>(
240 quote! { Ok(2) => |v| Ok(v + 1) |> |v| v + 2 <| Ok(2) },
241 )
242 .unwrap();
243 assert_eq!(chain.get_members().len(), 3);
244 assert!(chain.get_pat().is_none());
245 }
246
247 #[test]
248 fn it_parses_chain_from_initial_expr() {
249 let chain = ::syn::parse2::<ExprChainWithDefault>(quote! { Ok(2) }).unwrap();
250 assert_eq!(chain.get_members().len(), 1);
251 assert!(chain.get_pat().is_none());
252 }
253
254 #[test]
255 fn it_attempts_to_parse_empty_chain() {
256 assert!(::syn::parse2::<ExprChainWithDefault>(quote! {}).is_err());
257 }
258
259 #[test]
260 fn it_parses_chain_with_all_possible_command_expressions() {
261 let chain = ::syn::parse2::<ExprChainWithDefault>(quote! {
262 Ok(2) => |_| Ok(3) |> |_| 4 <| Ok(5) => |v| Ok(v) <= |_| Ok(8) ?> |v| println!("{}", v) -> |v| v
263 })
264 .unwrap();
265 let members = chain.get_members();
266 assert_eq!(
267 members[0],
268 ProcessWithDefault(
269 Some(ProcessActionExpr::Instant(ProcessExpr::Initial(
270 syn::parse2(quote! { Ok(2) }).unwrap()
271 ))),
272 None
273 )
274 );
275 assert_eq!(
276 members[1],
277 ProcessWithDefault(
278 Some(ProcessActionExpr::Instant(ProcessExpr::AndThen(
279 syn::parse2(quote! { |_| Ok(3) }).unwrap()
280 ))),
281 None
282 )
283 );
284
285 assert_eq!(
286 members[2],
287 ProcessWithDefault(
288 Some(ProcessActionExpr::Instant(ProcessExpr::Map(
289 syn::parse2(quote! { |_| 4 }).unwrap()
290 ))),
291 Some(DefaultActionExpr::Instant(DefaultExpr::Or(
292 syn::parse2(quote! { Ok(5) }).unwrap()
293 )))
294 )
295 );
296
297 assert_eq!(
298 members[3],
299 ProcessWithDefault(
300 Some(ProcessActionExpr::Instant(ProcessExpr::AndThen(
301 syn::parse2(quote! { |v| Ok(v) }).unwrap()
302 ))),
303 Some(DefaultActionExpr::Instant(DefaultExpr::OrElse(
304 syn::parse2(quote! { |_| Ok(8) }).unwrap()
305 )))
306 )
307 );
308
309 assert_eq!(
310 members[4],
311 ProcessWithDefault(
312 Some(ProcessActionExpr::Instant(ProcessExpr::Inspect(
313 syn::parse2(quote! { |v| println!("{}", v) }).unwrap()
314 ))),
315 None
316 )
317 );
318
319 assert_eq!(
320 members[5],
321 ProcessWithDefault(
322 Some(ProcessActionExpr::Instant(ProcessExpr::Then(
323 syn::parse2(quote! { |v| v }).unwrap()
324 ))),
325 None
326 )
327 );
328 }
329
330 #[test]
331 fn it_parses_chain_with_all_possible_deferred_command_expressions() {
332 let chain = ::syn::parse2::<ExprChainWithDefault>(quote! {
333 Ok(2) ~=> |_| Ok(3) ~|> |_| 4 ~<| Ok(5) ~=> |v| Ok(v) ~<= |_| Ok(8) ~?> |v| println!("{}", v) ~-> |v| v
334 }).unwrap();
335
336 let members = chain.get_members();
337 assert_eq!(
338 members[0],
339 ProcessWithDefault(
340 Some(ProcessActionExpr::Instant(ProcessExpr::Initial(
341 syn::parse2(quote! { Ok(2) }).unwrap()
342 ))),
343 None
344 )
345 );
346 assert_eq!(
347 members[1],
348 ProcessWithDefault(
349 Some(ProcessActionExpr::Deferred(ProcessExpr::AndThen(
350 syn::parse2(quote! { |_| Ok(3) }).unwrap()
351 ))),
352 None
353 )
354 );
355
356 assert_eq!(
357 members[2],
358 ProcessWithDefault(
359 Some(ProcessActionExpr::Deferred(ProcessExpr::Map(
360 syn::parse2(quote! { |_| 4 }).unwrap()
361 ))),
362 Some(DefaultActionExpr::Deferred(DefaultExpr::Or(
363 syn::parse2(quote! { Ok(5) }).unwrap()
364 )))
365 )
366 );
367
368 assert_eq!(
369 members[3],
370 ProcessWithDefault(
371 Some(ProcessActionExpr::Deferred(ProcessExpr::AndThen(
372 syn::parse2(quote! { |v| Ok(v) }).unwrap()
373 ))),
374 Some(DefaultActionExpr::Deferred(DefaultExpr::OrElse(
375 syn::parse2(quote! { |_| Ok(8) }).unwrap()
376 )))
377 )
378 );
379
380 assert_eq!(
381 members[4],
382 ProcessWithDefault(
383 Some(ProcessActionExpr::Deferred(ProcessExpr::Inspect(
384 syn::parse2(quote! { |v| println!("{}", v) }).unwrap()
385 ))),
386 None
387 )
388 );
389
390 assert_eq!(
391 members[5],
392 ProcessWithDefault(
393 Some(ProcessActionExpr::Deferred(ProcessExpr::Then(
394 syn::parse2(quote! { |v| v }).unwrap()
395 ))),
396 None
397 )
398 );
399 }
400}