1use std::future::Future;
2use std::pin::Pin;
3use std::task::{Context, Poll};
4
5use futures_util::ready;
6use pin_project::pin_project;
7
8use super::{Combine, Filter, FilterBase, Internal, Tuple};
9use crate::generic::CombinedTuples;
10use crate::reject::CombineRejection;
11
12#[derive(Clone, Copy, Debug)]
13pub struct And<T, U> {
14 pub(super) first: T,
15 pub(super) second: U,
16}
17
18impl<T, U> FilterBase for And<T, U>
19where
20 T: Filter,
21 T::Extract: Send,
22 U: Filter + Clone + Send,
23 <T::Extract as Tuple>::HList: Combine<<U::Extract as Tuple>::HList> + Send,
24 CombinedTuples<T::Extract, U::Extract>: Send,
25 U::Error: CombineRejection<T::Error>,
26{
27 type Extract = CombinedTuples<T::Extract, U::Extract>;
28 type Error = <U::Error as CombineRejection<T::Error>>::One;
29 type Future = AndFuture<T, U>;
30
31 fn filter(&self, _: Internal) -> Self::Future {
32 AndFuture {
33 state: State::First(self.first.filter(Internal), self.second.clone()),
34 }
35 }
36}
37
38#[allow(missing_debug_implementations)]
39#[pin_project]
40pub struct AndFuture<T: Filter, U: Filter> {
41 #[pin]
42 state: State<T::Future, T::Extract, U>,
43}
44
45#[pin_project(project = StateProj)]
46enum State<T, TE, U: Filter> {
47 First(#[pin] T, U),
48 Second(Option<TE>, #[pin] U::Future),
49 Done,
50}
51
52impl<T, U> Future for AndFuture<T, U>
53where
54 T: Filter,
55 U: Filter,
56 <T::Extract as Tuple>::HList: Combine<<U::Extract as Tuple>::HList> + Send,
57 U::Error: CombineRejection<T::Error>,
58{
59 type Output = Result<
60 CombinedTuples<T::Extract, U::Extract>,
61 <U::Error as CombineRejection<T::Error>>::One,
62 >;
63
64 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
65 self.project().state.poll(cx)
66 }
67}
68
69impl<T, TE, U, E> Future for State<T, TE, U>
70where
71 T: Future<Output = Result<TE, E>>,
72 U: Filter,
73 TE: Tuple,
74 TE::HList: Combine<<U::Extract as Tuple>::HList> + Send,
75 U::Error: CombineRejection<E>,
76{
77 type Output = Result<CombinedTuples<TE, U::Extract>, <U::Error as CombineRejection<E>>::One>;
78
79 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
80 loop {
81 match self.as_mut().project() {
82 StateProj::First(first, second) => {
83 let ex1 = ready!(first.poll(cx))?;
84 let fut2 = second.filter(Internal);
85 self.set(State::Second(Some(ex1), fut2));
86 }
87 StateProj::Second(ex1, second) => {
88 let ex2 = ready!(second.poll(cx))?;
89 let ex3 = ex1.take().unwrap().combine(ex2);
90 self.set(State::Done);
91 return Poll::Ready(Ok(ex3));
92 }
93 StateProj::Done => panic!("polled after complete"),
94 }
95 }
96 }
97}