Skip to main content

tower_http/csrf/
future.rs

1use std::future::Future;
2use std::pin::Pin;
3use std::task::{Context, Poll};
4
5use pin_project_lite::pin_project;
6
7pin_project! {
8    /// Response future for [`Csrf`].
9    ///
10    /// [`Csrf`]: super::Csrf
11    pub struct ResponseFuture<F>
12    where
13        F: Future,
14    {
15        #[pin]
16        kind: Kind<F>,
17    }
18}
19
20pin_project! {
21    #[project = KindProj]
22    enum Kind<F>
23    where
24        F: Future,
25    {
26        Future {
27            #[pin]
28            future: F,
29        },
30        Rejected {
31            response: Option<F::Output>,
32        },
33    }
34}
35
36impl<F> ResponseFuture<F>
37where
38    F: Future,
39{
40    pub(super) fn future(future: F) -> Self {
41        Self {
42            kind: Kind::Future { future },
43        }
44    }
45
46    pub(super) fn rejected(response: F::Output) -> Self {
47        Self {
48            kind: Kind::Rejected {
49                response: Some(response),
50            },
51        }
52    }
53}
54
55impl<F> Future for ResponseFuture<F>
56where
57    F: Future,
58{
59    type Output = F::Output;
60
61    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
62        match self.project().kind.project() {
63            KindProj::Future { future } => future.poll(cx),
64            KindProj::Rejected { response } => Poll::Ready(
65                response
66                    .take()
67                    .expect("ResponseFuture polled after completion"),
68            ),
69        }
70    }
71}