finchers_ext/
and.rs

1#![allow(missing_docs)]
2
3use super::maybe_done::MaybeDone;
4use finchers_core::endpoint::{Context, Endpoint, IntoEndpoint};
5use finchers_core::task::{self, Task};
6use finchers_core::{Error, Poll, PollResult};
7use std::fmt;
8
9pub fn new<E1, E2>(e1: E1, e2: E2) -> And<E1::Endpoint, E2::Endpoint>
10where
11    E1: IntoEndpoint,
12    E2: IntoEndpoint,
13    E1::Output: Send,
14    E2::Output: Send,
15{
16    And {
17        e1: e1.into_endpoint(),
18        e2: e2.into_endpoint(),
19    }
20}
21
22#[derive(Copy, Clone, Debug)]
23pub struct And<E1, E2> {
24    e1: E1,
25    e2: E2,
26}
27
28impl<E1, E2> Endpoint for And<E1, E2>
29where
30    E1: Endpoint,
31    E2: Endpoint,
32    E1::Output: Send,
33    E2::Output: Send,
34{
35    type Output = (E1::Output, E2::Output);
36    type Task = AndTask<E1::Task, E2::Task>;
37
38    fn apply(&self, cx: &mut Context) -> Option<Self::Task> {
39        let f1 = self.e1.apply(cx)?;
40        let f2 = self.e2.apply(cx)?;
41        Some(AndTask {
42            f1: MaybeDone::Pending(f1),
43            f2: MaybeDone::Pending(f2),
44        })
45    }
46}
47
48pub struct AndTask<F1: Task, F2: Task> {
49    f1: MaybeDone<F1>,
50    f2: MaybeDone<F2>,
51}
52
53impl<T1, T2> fmt::Debug for AndTask<T1, T2>
54where
55    T1: Task + fmt::Debug,
56    T2: Task + fmt::Debug,
57    T1::Output: fmt::Debug,
58    T2::Output: fmt::Debug,
59{
60    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61        f.debug_struct("AndTask")
62            .field("t1", &self.f1)
63            .field("t2", &self.f2)
64            .finish()
65    }
66}
67
68impl<F1, F2> Task for AndTask<F1, F2>
69where
70    F1: Task,
71    F2: Task,
72    F1::Output: Send,
73    F2::Output: Send,
74{
75    type Output = (F1::Output, F2::Output);
76
77    fn poll_task(&mut self, cx: &mut task::Context) -> PollResult<Self::Output, Error> {
78        let mut all_done = match self.f1.poll_done(cx) {
79            Ok(done) => done,
80            Err(e) => {
81                self.f1.erase();
82                self.f2.erase();
83                return Poll::Ready(Err(e));
84            }
85        };
86        all_done = match self.f2.poll_done(cx) {
87            Ok(done) => all_done && done,
88            Err(e) => {
89                self.f1.erase();
90                self.f2.erase();
91                return Poll::Ready(Err(e));
92            }
93        };
94
95        if all_done {
96            Poll::Ready(Ok((self.f1.take_item(), self.f2.take_item())))
97        } else {
98            Poll::Pending
99        }
100    }
101}