1use super::maybe_done::MaybeDone;
2use finchers_core::endpoint::{Context, Endpoint, IntoEndpoint};
3use finchers_core::task::{self, Task};
4use finchers_core::{Error, Poll, PollResult};
5use std::{fmt, mem};
6
7pub fn all<I>(iter: I) -> All<<I::Item as IntoEndpoint>::Endpoint>
9where
10 I: IntoIterator,
11 I::Item: IntoEndpoint,
12 <I::Item as IntoEndpoint>::Output: Send,
13{
14 All {
15 inner: iter.into_iter().map(IntoEndpoint::into_endpoint).collect(),
16 }
17}
18
19#[allow(missing_docs)]
20#[derive(Clone, Debug)]
21pub struct All<E> {
22 inner: Vec<E>,
23}
24
25impl<E> Endpoint for All<E>
26where
27 E: Endpoint,
28 E::Output: Send,
29{
30 type Output = Vec<E::Output>;
31 type Task = AllTask<E::Task>;
32
33 fn apply(&self, cx: &mut Context) -> Option<Self::Task> {
34 let mut elems = Vec::with_capacity(self.inner.len());
35 for e in &self.inner {
36 let f = e.apply(cx)?;
37 elems.push(MaybeDone::Pending(f));
38 }
39 Some(AllTask { elems })
40 }
41}
42
43#[allow(missing_docs)]
44pub struct AllTask<T: Task> {
45 elems: Vec<MaybeDone<T>>,
46}
47
48impl<T> fmt::Debug for AllTask<T>
49where
50 T: Task + fmt::Debug,
51 T::Output: fmt::Debug,
52{
53 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54 f.debug_struct("AllTask").field("elems", &self.elems).finish()
55 }
56}
57
58impl<T> Task for AllTask<T>
59where
60 T: Task,
61 T::Output: Send,
62{
63 type Output = Vec<T::Output>;
64
65 fn poll_task(&mut self, cx: &mut task::Context) -> PollResult<Self::Output, Error> {
66 let mut all_done = true;
67 for i in 0..self.elems.len() {
68 match self.elems[i].poll_done(cx) {
69 Ok(done) => all_done = all_done & done,
70 Err(e) => {
71 self.elems = Vec::new();
72 return Poll::Ready(Err(e));
73 }
74 }
75 }
76 if all_done {
77 let elems: Vec<T::Output> = mem::replace(&mut self.elems, Vec::new())
78 .into_iter()
79 .map(|mut m| m.take_item())
80 .collect();
81 Into::into(Ok(elems))
82 } else {
83 Poll::Pending
84 }
85 }
86}