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}