ts_webapi/middleware/futures/
defined.rs

1//! A future defined at the time the middleware is called.
2
3use core::{
4    pin::Pin,
5    task::{Context, Poll, ready},
6};
7
8use http::{Response, StatusCode};
9use http_body::Body;
10use pin_project_lite::pin_project;
11
12pin_project! {
13    /// A future defined at the time the middleware is called.
14    pub struct DefinedFuture<F> {
15        #[pin]
16        inner: DefinedFutureKind<F>,
17    }
18}
19
20pin_project! {
21    #[project = DefinedFutureKindProj]
22    enum DefinedFutureKind<F> {
23        Proceeding {
24            #[pin]
25            future: F,
26        },
27        Status {
28            status: StatusCode
29        },
30    }
31}
32
33impl<F> DefinedFuture<F> {
34    /// This future should just return the given status.
35    pub fn return_status(status: StatusCode) -> Self {
36        Self {
37            inner: DefinedFutureKind::Status { status },
38        }
39    }
40
41    /// This future should proceed with the inner future.
42    pub fn proceed(future: F) -> Self {
43        Self {
44            inner: DefinedFutureKind::Proceeding { future },
45        }
46    }
47}
48
49impl<B, F, E> Future for DefinedFuture<F>
50where
51    B: Body + Default,
52    F: Future<Output = Result<Response<B>, E>>,
53{
54    type Output = Result<Response<B>, E>;
55
56    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
57        let response = match self.project().inner.project() {
58            DefinedFutureKindProj::Proceeding { future } => ready!(future.poll(cx))?,
59            DefinedFutureKindProj::Status { status } => Response::builder()
60                .status(*status)
61                .body(B::default())
62                .expect("error response should be valid response"),
63        };
64        Poll::Ready(Ok(response))
65    }
66}