finchers_ext/
all.rs

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
7/// Create an endpoint which evaluates the all endpoint in the given collection sequentially.
8pub 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}