1use crate::event::convert::Try;
24use crate::event::{And, Handled, Handler, Or, TryAnd, TryOr, TryOrUnmatched};
25
26#[derive(Debug)]
28struct BoundHandler<'h, H, S, E> {
29 handler: &'h mut H,
30 state: &'h mut S,
31 event: &'h E,
32}
33
34impl<'h, H, S, E> BoundHandler<'h, H, S, E>
35where
36 H: Handler<S, E>,
37{
38 pub fn call(self) -> Handled<H::Output> {
39 self.handler.call(self.state, self.event)
40 }
41}
42
43trait DynamicChain<H> {
46 fn chain<S, E, F>(&mut self, state: &mut S, event: &E, f: F) -> Handled<H::Output>
47 where
48 H: Handler<S, E>,
49 F: FnMut(Handled<H::Output>, BoundHandler<'_, H, S, E>) -> Handled<H::Output>;
50}
51
52impl<H> DynamicChain<H> for [H] {
53 fn chain<S, E, F>(&mut self, state: &mut S, event: &E, mut f: F) -> Handled<H::Output>
59 where
60 H: Handler<S, E>,
61 F: FnMut(Handled<H::Output>, BoundHandler<'_, H, S, E>) -> Handled<H::Output>,
62 {
63 self.iter_mut()
64 .fold(None, |chain: Option<Handled<_>>, handler| {
65 if let Some(handled) = chain {
66 Some(f(handled, BoundHandler { handler, state, event }))
67 } else {
68 Some(handler.call(state, event))
69 }
70 })
71 .unwrap_or(Handled::Unmatched)
72 }
73}
74
75#[derive(Clone, Copy, Debug)]
76pub struct DynamicAnd<T>(T);
77
78impl<S, E, H> Handler<S, E> for DynamicAnd<Vec<H>>
79where
80 H: Handler<S, E>,
81{
82 type Output = H::Output;
83
84 fn call(&mut self, state: &mut S, event: &E) -> Handled<Self::Output> {
85 self.0
86 .as_mut_slice()
87 .chain(state, event, |previous, next| previous.and_then(|_| next.call()))
88 }
89}
90
91#[derive(Clone, Copy, Debug)]
92pub struct DynamicTryAnd<T>(T);
93
94impl<S, E, H> Handler<S, E> for DynamicTryAnd<Vec<H>>
95where
96 H: Handler<S, E>,
97 H::Output: Try,
98{
99 type Output = H::Output;
100
101 fn call(&mut self, state: &mut S, event: &E) -> Handled<Self::Output> {
102 self.0
103 .as_mut_slice()
104 .chain(state, event, |previous, next| previous.try_and_then(|_| next.call()))
105 }
106}
107
108#[derive(Clone, Copy, Debug)]
109pub struct DynamicOr<T>(T);
110
111impl<S, E, H> Handler<S, E> for DynamicOr<Vec<H>>
112where
113 H: Handler<S, E>,
114{
115 type Output = H::Output;
116
117 fn call(&mut self, state: &mut S, event: &E) -> Handled<Self::Output> {
118 self.0.as_mut_slice().chain(state, event, |previous, next| previous.or_else(|| next.call()))
119 }
120}
121
122#[derive(Clone, Copy, Debug)]
123pub struct DynamicTryOr<T>(T);
124
125impl<S, E, H> Handler<S, E> for DynamicTryOr<Vec<H>>
126where
127 H: Handler<S, E>,
128 H::Output: Try,
129{
130 type Output = H::Output;
131
132 fn call(&mut self, state: &mut S, event: &E) -> Handled<Self::Output> {
133 self.0
134 .as_mut_slice()
135 .chain(state, event, |previous, next| previous.try_or_else(|| next.call()))
136 .try_or_else(|| Handled::Unmatched)
140 }
141}
142
143pub trait AndChain<S, E> {
145 type Combinator: Handler<S, E>;
146
147 fn chain(self) -> Self::Combinator;
148}
149
150impl<S, E, H> AndChain<S, E> for Vec<H>
151where
152 H: Handler<S, E>,
153{
154 type Combinator = DynamicAnd<Vec<H>>;
155
156 fn chain(self) -> Self::Combinator {
157 DynamicAnd(self)
158 }
159}
160
161pub trait TryAndChain<S, E> {
163 type Combinator: Handler<S, E>;
164
165 fn chain(self) -> Self::Combinator;
166}
167
168impl<S, E, H> TryAndChain<S, E> for Vec<H>
169where
170 H: Handler<S, E>,
171 H::Output: Try,
172{
173 type Combinator = DynamicTryAnd<Vec<H>>;
174
175 fn chain(self) -> Self::Combinator {
176 DynamicTryAnd(self)
177 }
178}
179
180pub trait OrChain<S, E> {
182 type Combinator: Handler<S, E>;
183
184 fn chain(self) -> Self::Combinator;
185}
186
187impl<S, E, H> OrChain<S, E> for Vec<H>
188where
189 H: Handler<S, E>,
190{
191 type Combinator = DynamicOr<Vec<H>>;
192
193 fn chain(self) -> Self::Combinator {
194 DynamicOr(self)
195 }
196}
197
198pub trait TryOrChain<S, E> {
200 type Combinator: Handler<S, E>;
201
202 fn chain(self) -> Self::Combinator;
203}
204
205impl<S, E, H> TryOrChain<S, E> for Vec<H>
206where
207 H: Handler<S, E>,
208 H::Output: Try,
209{
210 type Combinator = DynamicTryOr<Vec<H>>;
211
212 fn chain(self) -> Self::Combinator {
213 DynamicTryOr(self)
214 }
215}
216
217pub fn and<S, E, T>(
221 handlers: T,
222) -> impl Handler<S, E, Output = <T::Combinator as Handler<S, E>>::Output>
223where
224 T: AndChain<S, E>,
225{
226 handlers.chain()
227}
228
229pub fn try_and<S, E, T>(
237 handlers: T,
238) -> impl Handler<S, E, Output = <T::Combinator as Handler<S, E>>::Output>
239where
240 T: TryAndChain<S, E>,
241{
242 handlers.chain()
243}
244
245pub fn or<S, E, T>(
250 handlers: T,
251) -> impl Handler<S, E, Output = <T::Combinator as Handler<S, E>>::Output>
252where
253 T: OrChain<S, E>,
254{
255 handlers.chain()
256}
257
258pub fn try_or<S, E, T>(
268 handlers: T,
269) -> impl Handler<S, E, Output = <T::Combinator as Handler<S, E>>::Output>
270where
271 T: TryOrChain<S, E>,
272{
273 handlers.chain()
274}
275
276macro_rules! with_nonunary_tuples {
281 ($f:ident, ( $head:ident,$tail:ident$(,)? )$(,)?) => {
282 $f!(($head, $tail));
283 };
284 ($f:ident, ( $head:ident,$body:ident,$($tail:ident),+$(,)? )$(,)?) => {
285 $f!(($head,$body,$($tail,)*));
286 with_nonunary_tuples!($f, ( $body,$($tail,)+ ));
287 };
288}
289macro_rules! forward_static_combinator_chain_output {
294 ($combinator:ident, ( $($forward:ident),*$(,)? )) => {
295 forward_static_combinator_chain_output!($combinator, ($($forward,)*); ())
296 };
297 ($combinator:ident, ( $head:ident,$($tail:ident),*$(,)? ); ( $($reverse:ident),*$(,)? )) => {
298 forward_static_combinator_chain_output!($combinator, ($($tail,)*); ($head,$($reverse,)*))
299 };
300 ($combinator:ident, ( $(,)? ); ( $($reverse:ident),*$(,)? )) => {
303 reverse_static_combinator_chain_output!($combinator, ( $($reverse,)* ))
304 };
305}
306macro_rules! reverse_static_combinator_chain_output {
311 ($combinator:ident, ( $head:ident,$body:ident,$($tail:ident,)+ )$(,)?) => {
312 $combinator<reverse_static_combinator_chain_output!($combinator, ($body,$($tail,)+)), $head>
313 };
314 ($combinator:ident, ( $head:ident,$tail:ident$(,)? )$(,)?) => {
315 $combinator<$tail, $head>
316 };
317}
318macro_rules! impl_static_combinator_chain {
323 (( $head:ident,$($tail:ident),+$(,)? )$(,)?) => {
324 impl<S, E, $head, $($tail,)+> AndChain<S, E> for ($head, $($tail,)+)
325 where
326 $head: Handler<S, E>,
327 $(
328 $tail: Handler<S, E>,
329 )+
330 {
331 type Combinator = forward_static_combinator_chain_output!(And, ($head, $($tail,)+));
332
333 #[allow(non_snake_case)]
334 fn chain(self) -> Self::Combinator {
335 let ($head, $($tail,)+) = self;
336 $head
337 $(
338 .and($tail)
339 )+
340 }
341 }
342
343 impl<S, E, R, $head, $($tail,)+> TryAndChain<S, E> for ($head, $($tail,)+)
344 where
345 $head: Handler<S, E>,
346 $head::Output: Try<Residual = R>,
347 $(
348 $tail: Handler<S, E>,
349 $tail::Output: Try<Residual = R>,
350 )+
351 {
352 type Combinator = forward_static_combinator_chain_output!(TryAnd, ($head, $($tail,)+));
353
354 #[allow(non_snake_case)]
355 fn chain(self) -> Self::Combinator {
356 let ($head, $($tail,)+) = self;
357 $head
358 $(
359 .try_and($tail)
360 )+
361 }
362 }
363
364 impl<S, E, O, $head, $($tail,)+> OrChain<S, E> for ($head, $($tail,)+)
365 where
366 $head: Handler<S, E, Output = O>,
367 $(
368 $tail: Handler<S, E, Output = O>,
369 )+
370 {
371 type Combinator = forward_static_combinator_chain_output!(Or, ($head, $($tail,)+));
372
373 #[allow(non_snake_case)]
374 fn chain(self) -> Self::Combinator {
375 let ($head, $($tail,)+) = self;
376 $head
377 $(
378 .or($tail)
379 )+
380 }
381 }
382
383 impl<S, E, O, $head, $($tail,)+> TryOrChain<S, E> for ($head, $($tail,)+)
384 where
385 O: Try,
386 $head: Handler<S, E, Output = O>,
387 $(
388 $tail: Handler<S, E, Output = O>,
389 )+
390 {
391 type Combinator = TryOrUnmatched<
392 forward_static_combinator_chain_output!(TryOr, ($head, $($tail,)+))
393 >;
394
395 #[allow(non_snake_case)]
396 fn chain(self) -> Self::Combinator {
397 let ($head, $($tail,)+) = self;
398 $head
399 $(
400 .try_or($tail)
401 )+
402 .try_or_unmatched()
406 }
407 }
408 };
409}
410with_nonunary_tuples!(impl_static_combinator_chain, (T1, T2, T3, T4, T5, T6, T7, T8));
411
412#[cfg(test)]
413mod tests {
414 use crate::event::{self, branch, Handled, Handler};
415
416 fn unmatched<S, E, T, F>(mut f: F) -> impl Handler<S, E, Output = T>
418 where
419 F: FnMut(&mut S, &E) -> T,
420 {
421 move |state: &mut S, event: &E| {
422 let _ = f(state, event);
423 Handled::Unmatched
424 }
425 }
426
427 fn output<S, E, T, F>(mut f: F) -> impl FnMut(&mut S, &E) -> T
430 where
431 F: FnMut() -> T,
432 {
433 move |_, _| f()
434 }
435
436 fn breadcrumb<E, T, B, F>(crumb: B, mut f: F) -> impl FnMut(&mut Vec<B>, &E) -> T
440 where
441 B: Copy,
442 F: FnMut() -> T,
443 {
444 move |breadcrumbs: &mut Vec<_>, _| {
445 breadcrumbs.push(crumb);
446 f()
447 }
448 }
449
450 const fn unit() {}
451
452 const fn some() -> Option<()> {
453 Some(())
454 }
455
456 const fn none() -> Option<()> {
457 None
458 }
459
460 #[test]
461 fn static_and_executes_in_order() {
462 let mut breadcrumbs = vec![];
463 branch::and((
464 event::matched(breadcrumb(0, unit)),
465 event::matched(breadcrumb(1, unit)),
466 event::matched(breadcrumb(2, unit)),
467 event::matched(breadcrumb(3, unit)),
468 event::matched(breadcrumb(4, unit)),
469 ))
470 .call(&mut breadcrumbs, &());
471 assert_eq!(breadcrumbs, &[0, 1, 2, 3, 4]);
472 }
473
474 #[test]
475 fn static_and_executes_until_unmatched() {
476 let mut breadcrumbs = vec![];
477 branch::and((
478 event::matched(breadcrumb(0, unit)),
479 unmatched(breadcrumb(1, unit)),
480 event::matched(breadcrumb(2, unit)),
481 ))
482 .call(&mut breadcrumbs, &());
483 assert_eq!(breadcrumbs, &[0, 1]);
484 }
485
486 #[test]
487 fn static_and_matched_if_all_matched() {
488 let handled = branch::and((
489 event::matched(output(unit)),
490 event::matched(output(unit)),
491 event::matched(output(unit)),
492 ))
493 .call(&mut (), &());
494 assert!(handled.is_matched());
495 }
496
497 #[test]
498 fn static_and_unmatched_if_any_unmatched() {
499 let handled = branch::and((
500 event::matched(output(unit)),
501 unmatched(output(unit)),
502 event::matched(output(unit)),
503 ))
504 .call(&mut (), &());
505 assert!(handled.is_unmatched());
506 }
507
508 #[test]
509 fn dynamic_and_executes_in_order() {
510 let mut breadcrumbs = vec![];
511 branch::and(vec![
512 event::boxed(event::matched(breadcrumb(0, unit))),
513 event::boxed(event::matched(breadcrumb(1, unit))),
514 event::boxed(event::matched(breadcrumb(2, unit))),
515 event::boxed(event::matched(breadcrumb(3, unit))),
516 event::boxed(event::matched(breadcrumb(4, unit))),
517 ])
518 .call(&mut breadcrumbs, &());
519 assert_eq!(breadcrumbs, &[0, 1, 2, 3, 4]);
520 }
521
522 #[test]
523 fn dynamic_and_executes_until_unmatched() {
524 let mut breadcrumbs = vec![];
525 branch::and(vec![
526 event::boxed(event::matched(breadcrumb(0, unit))),
527 event::boxed(unmatched(breadcrumb(1, unit))),
528 event::boxed(event::matched(breadcrumb(2, unit))),
529 ])
530 .call(&mut breadcrumbs, &());
531 assert_eq!(breadcrumbs, &[0, 1]);
532 }
533
534 #[test]
535 fn dynamic_and_matched_if_all_matched() {
536 let handled = branch::and(vec![
537 event::boxed(event::matched(output(unit))),
538 event::boxed(event::matched(output(unit))),
539 event::boxed(event::matched(output(unit))),
540 ])
541 .call(&mut (), &());
542 assert!(handled.is_matched());
543 }
544
545 #[test]
546 fn dynamic_and_unmatched_if_any_unmatched() {
547 let handled = branch::and(vec![
548 event::boxed(event::matched(output(unit))),
549 event::boxed(unmatched(output(unit))),
550 event::boxed(event::matched(output(unit))),
551 ])
552 .call(&mut (), &());
553 assert!(handled.is_unmatched());
554 }
555
556 #[test]
557 fn static_try_and_executes_in_order() {
558 let mut breadcrumbs = vec![];
559 branch::try_and((
560 event::matched(breadcrumb(0, some)),
561 event::matched(breadcrumb(1, some)),
562 event::matched(breadcrumb(2, some)),
563 event::matched(breadcrumb(3, some)),
564 event::matched(breadcrumb(4, some)),
565 ))
566 .call(&mut breadcrumbs, &());
567 assert_eq!(breadcrumbs, &[0, 1, 2, 3, 4]);
568 }
569
570 #[test]
571 fn static_try_and_executes_until_unmatched() {
572 let mut breadcrumbs = vec![];
573 branch::try_and((
574 event::matched(breadcrumb(0, some)),
575 unmatched(breadcrumb(1, some)),
576 event::matched(breadcrumb(2, some)),
577 ))
578 .call(&mut breadcrumbs, &());
579 assert_eq!(breadcrumbs, &[0, 1]);
580 }
581
582 #[test]
583 fn static_try_and_executes_until_matched_residual() {
584 let mut breadcrumbs = vec![];
585 branch::try_and((
586 event::matched(breadcrumb(0, some)),
587 event::matched(breadcrumb(1, none)),
588 event::matched(breadcrumb(2, some)),
589 ))
590 .call(&mut breadcrumbs, &());
591 assert_eq!(breadcrumbs, &[0, 1]);
592 }
593
594 #[test]
595 fn static_try_and_matched_if_all_matched_output() {
596 let handled = branch::try_and((
597 event::matched(output(some)),
598 event::matched(output(some)),
599 event::matched(output(some)),
600 ))
601 .call(&mut (), &());
602 assert!(handled.is_matched());
603 }
604
605 #[test]
606 fn static_try_and_unmatched_if_any_unmatched() {
607 let handled = branch::try_and((
608 event::matched(output(some)),
609 unmatched(output(some)),
610 event::matched(output(some)),
611 ))
612 .call(&mut (), &());
613 assert!(handled.is_unmatched());
614 }
615
616 #[test]
617 fn static_try_and_unmatched_if_any_matched_residual() {
618 let handled = branch::try_and((
619 event::matched(output(some)),
620 event::matched(output(none)),
621 event::matched(output(some)),
622 ))
623 .call(&mut (), &());
624 assert!(handled.is_unmatched());
625 }
626
627 #[test]
628 fn dynamic_try_and_executes_in_order() {
629 let mut breadcrumbs = vec![];
630 branch::try_and(vec![
631 event::boxed(event::matched(breadcrumb(0, some))),
632 event::boxed(event::matched(breadcrumb(1, some))),
633 event::boxed(event::matched(breadcrumb(2, some))),
634 event::boxed(event::matched(breadcrumb(3, some))),
635 event::boxed(event::matched(breadcrumb(4, some))),
636 ])
637 .call(&mut breadcrumbs, &());
638 assert_eq!(breadcrumbs, &[0, 1, 2, 3, 4]);
639 }
640
641 #[test]
642 fn dynamic_try_and_executes_until_unmatched() {
643 let mut breadcrumbs = vec![];
644 branch::try_and(vec![
645 event::boxed(event::matched(breadcrumb(0, some))),
646 event::boxed(unmatched(breadcrumb(1, some))),
647 event::boxed(event::matched(breadcrumb(2, some))),
648 ])
649 .call(&mut breadcrumbs, &());
650 assert_eq!(breadcrumbs, &[0, 1]);
651 }
652
653 #[test]
654 fn dynamic_try_and_executes_until_matched_residual() {
655 let mut breadcrumbs = vec![];
656 branch::try_and(vec![
657 event::boxed(event::matched(breadcrumb(0, some))),
658 event::boxed(event::matched(breadcrumb(1, none))),
659 event::boxed(event::matched(breadcrumb(2, some))),
660 ])
661 .call(&mut breadcrumbs, &());
662 assert_eq!(breadcrumbs, &[0, 1]);
663 }
664
665 #[test]
666 fn dynamic_try_and_matched_if_all_matched_output() {
667 let handled = branch::try_and(vec![
668 event::boxed(event::matched(output(some))),
669 event::boxed(event::matched(output(some))),
670 event::boxed(event::matched(output(some))),
671 ])
672 .call(&mut (), &());
673 assert!(handled.is_matched());
674 }
675
676 #[test]
677 fn dynamic_try_and_unmatched_if_any_unmatched() {
678 let handled = branch::try_and(vec![
679 event::boxed(event::matched(output(some))),
680 event::boxed(unmatched(output(some))),
681 event::boxed(event::matched(output(some))),
682 ])
683 .call(&mut (), &());
684 assert!(handled.is_unmatched());
685 }
686
687 #[test]
688 fn dynamic_try_and_unmatched_if_any_matched_residual() {
689 let handled = branch::try_and(vec![
690 event::boxed(event::matched(output(some))),
691 event::boxed(event::matched(output(none))),
692 event::boxed(event::matched(output(some))),
693 ])
694 .call(&mut (), &());
695 assert!(handled.is_unmatched());
696 }
697
698 #[test]
699 fn static_or_executes_in_order() {
700 let mut breadcrumbs = vec![];
701 branch::or((
702 unmatched(breadcrumb(0, unit)),
703 unmatched(breadcrumb(1, unit)),
704 unmatched(breadcrumb(2, unit)),
705 unmatched(breadcrumb(3, unit)),
706 unmatched(breadcrumb(4, unit)),
707 ))
708 .call(&mut breadcrumbs, &());
709 assert_eq!(breadcrumbs, &[0, 1, 2, 3, 4]);
710 }
711
712 #[test]
713 fn static_or_executes_until_matched() {
714 let mut breadcrumbs = vec![];
715 branch::or((
716 unmatched(breadcrumb(0, unit)),
717 event::matched(breadcrumb(1, unit)),
718 unmatched(breadcrumb(2, unit)),
719 ))
720 .call(&mut breadcrumbs, &());
721 assert_eq!(breadcrumbs, &[0, 1]);
722 }
723
724 #[test]
725 fn static_or_matched_if_any_matched() {
726 let handled = branch::or((
727 unmatched(output(unit)),
728 unmatched(output(unit)),
729 event::matched(output(unit)),
730 ))
731 .call(&mut (), &());
732 assert!(handled.is_matched());
733 }
734
735 #[test]
736 fn static_or_unmatched_if_all_unmatched() {
737 let handled =
738 branch::or((unmatched(output(unit)), unmatched(output(unit)), unmatched(output(unit))))
739 .call(&mut (), &());
740 assert!(handled.is_unmatched());
741 }
742
743 #[test]
744 fn dynamic_or_executes_in_order() {
745 let mut breadcrumbs = vec![];
746 branch::or(vec![
747 event::boxed(unmatched(breadcrumb(0, unit))),
748 event::boxed(unmatched(breadcrumb(1, unit))),
749 event::boxed(unmatched(breadcrumb(2, unit))),
750 event::boxed(unmatched(breadcrumb(3, unit))),
751 event::boxed(unmatched(breadcrumb(4, unit))),
752 ])
753 .call(&mut breadcrumbs, &());
754 assert_eq!(breadcrumbs, &[0, 1, 2, 3, 4]);
755 }
756
757 #[test]
758 fn dynamic_or_executes_until_matched() {
759 let mut breadcrumbs = vec![];
760 branch::or(vec![
761 event::boxed(unmatched(breadcrumb(0, unit))),
762 event::boxed(event::matched(breadcrumb(1, unit))),
763 event::boxed(unmatched(breadcrumb(2, unit))),
764 ])
765 .call(&mut breadcrumbs, &());
766 assert_eq!(breadcrumbs, &[0, 1]);
767 }
768
769 #[test]
770 fn dynamic_or_matched_if_any_matched() {
771 let handled = branch::or(vec![
772 event::boxed(unmatched(output(unit))),
773 event::boxed(unmatched(output(unit))),
774 event::boxed(event::matched(output(unit))),
775 ])
776 .call(&mut (), &());
777 assert!(handled.is_matched());
778 }
779
780 #[test]
781 fn dynamic_or_unmatched_if_all_unmatched() {
782 let handled = branch::or(vec![
783 event::boxed(unmatched(output(unit))),
784 event::boxed(unmatched(output(unit))),
785 event::boxed(unmatched(output(unit))),
786 ])
787 .call(&mut (), &());
788 assert!(handled.is_unmatched());
789 }
790
791 #[test]
792 fn static_try_or_executes_in_order() {
793 let mut breadcrumbs = vec![];
794 branch::try_or((
795 unmatched(breadcrumb(0, some)),
796 unmatched(breadcrumb(1, some)),
797 unmatched(breadcrumb(2, some)),
798 ))
799 .call(&mut breadcrumbs, &());
800 assert_eq!(breadcrumbs, &[0, 1, 2]);
801 }
802
803 #[test]
804 fn static_try_or_executes_until_matched_output() {
805 let mut breadcrumbs = vec![];
806 branch::try_or((
807 unmatched(breadcrumb(0, some)),
808 event::matched(breadcrumb(1, some)),
809 unmatched(breadcrumb(2, some)),
810 ))
811 .call(&mut breadcrumbs, &());
812 assert_eq!(breadcrumbs, &[0, 1]);
813 }
814
815 #[test]
816 fn static_try_or_executes_through_matched_residual() {
817 let mut breadcrumbs = vec![];
818 branch::try_or((
819 unmatched(breadcrumb(0, some)),
820 event::matched(breadcrumb(1, none)),
821 event::matched(breadcrumb(2, none)),
822 ))
823 .call(&mut breadcrumbs, &());
824 assert_eq!(breadcrumbs, &[0, 1, 2]);
825 }
826
827 #[test]
828 fn static_try_or_matched_if_any_matched_output() {
829 let handled = branch::try_or((
830 unmatched(output(some)),
831 unmatched(output(some)),
832 event::matched(output(some)),
833 ))
834 .call(&mut (), &());
835 assert!(handled.is_matched());
836 }
837
838 #[test]
839 fn static_try_or_unmatched_if_all_unmatched_or_matched_residual() {
840 let handled = branch::try_or((
841 unmatched(output(some)),
842 unmatched(output(some)),
843 unmatched(output(some)),
844 ))
845 .call(&mut (), &());
846 assert!(handled.is_unmatched());
847
848 let handled = branch::try_or((
849 event::matched(output(none)),
850 event::matched(output(none)),
851 event::matched(output(none)),
852 ))
853 .call(&mut (), &());
854 assert!(handled.is_unmatched());
855
856 let handled = branch::try_or((
857 event::matched(output(none)),
858 unmatched(output(some)),
859 unmatched(output(some)),
860 ))
861 .call(&mut (), &());
862 assert!(handled.is_unmatched());
863 }
864
865 #[test]
866 fn dynamic_try_or_executes_in_order() {
867 let mut breadcrumbs = vec![];
868 branch::try_or(vec![
869 event::boxed(unmatched(breadcrumb(0, some))),
870 event::boxed(unmatched(breadcrumb(1, some))),
871 event::boxed(unmatched(breadcrumb(2, some))),
872 event::boxed(unmatched(breadcrumb(3, some))),
873 event::boxed(unmatched(breadcrumb(4, some))),
874 ])
875 .call(&mut breadcrumbs, &());
876 assert_eq!(breadcrumbs, &[0, 1, 2, 3, 4]);
877 }
878
879 #[test]
880 fn dynamic_try_or_executes_until_matched_output() {
881 let mut breadcrumbs = vec![];
882 branch::try_or(vec![
883 event::boxed(unmatched(breadcrumb(0, some))),
884 event::boxed(event::matched(breadcrumb(1, some))),
885 event::boxed(unmatched(breadcrumb(2, some))),
886 ])
887 .call(&mut breadcrumbs, &());
888 assert_eq!(breadcrumbs, &[0, 1]);
889 }
890
891 #[test]
892 fn dynamic_try_or_executes_through_matched_residual() {
893 let mut breadcrumbs = vec![];
894 branch::try_or(vec![
895 event::boxed(unmatched(breadcrumb(0, some))),
896 event::boxed(event::matched(breadcrumb(1, none))),
897 event::boxed(event::matched(breadcrumb(2, none))),
898 ])
899 .call(&mut breadcrumbs, &());
900 assert_eq!(breadcrumbs, &[0, 1, 2]);
901 }
902
903 #[test]
904 fn dynamic_try_or_matched_if_any_matched_output() {
905 let handled = branch::try_or(vec![
906 event::boxed(unmatched(output(some))),
907 event::boxed(unmatched(output(some))),
908 event::boxed(event::matched(output(some))),
909 ])
910 .call(&mut (), &());
911 assert!(handled.is_matched());
912 }
913
914 #[test]
915 fn dynamic_try_or_unmatched_if_all_unmatched_or_matched_residual() {
916 let handled = branch::try_or(vec![
917 event::boxed(unmatched(output(some))),
918 event::boxed(unmatched(output(some))),
919 event::boxed(unmatched(output(some))),
920 ])
921 .call(&mut (), &());
922 assert!(handled.is_unmatched());
923
924 let handled = branch::try_or(vec![
925 event::boxed(event::matched(output(none))),
926 event::boxed(event::matched(output(none))),
927 event::boxed(event::matched(output(none))),
928 ])
929 .call(&mut (), &());
930 assert!(handled.is_unmatched());
931
932 let handled = branch::try_or(vec![
933 event::boxed(event::matched(output(none))),
934 event::boxed(unmatched(output(some))),
935 event::boxed(unmatched(output(some))),
936 ])
937 .call(&mut (), &());
938 assert!(handled.is_unmatched());
939 }
940}