traq_bot_http/handler/
future.rs1use std::future::Future;
2use std::marker::PhantomData;
3use std::pin::Pin;
4use std::task::{Context, Poll};
5
6use futures_core::ready;
7use http::{Response, StatusCode};
8use http_body::Body;
9use pin_project_lite::pin_project;
10use tower_service::Service;
11
12use crate::error::{Error, Result};
13use crate::events::Event;
14use crate::parser::ParseRequest;
15
16pin_project! {
17 #[must_use]
35 #[project = WrapErrorFutureProject]
36 #[derive(Debug)]
37 pub struct WrapErrorFuture<F, E> {
38 _error: PhantomData<E>,
39 #[pin]
40 inner: F,
41 }
42}
43
44impl<F, E> WrapErrorFuture<F, E> {
45 pub(crate) fn new(inner: F) -> Self {
46 Self {
47 _error: PhantomData,
48 inner,
49 }
50 }
51}
52
53impl<F, E> Future for WrapErrorFuture<F, E>
54where
55 F: Future<Output = Result<(), E>>,
56 E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
57{
58 type Output = Result<()>;
59
60 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
61 let s = self.project();
62 let res = ready!(s.inner.poll(cx));
63 Poll::Ready(res.map_err(Error::handler))
64 }
65}
66
67pin_project! {
68 #[must_use]
69 #[project = HandlerCallParseRequestProject]
70 struct HandlerCallParseRequest<B, S>
71 where
72 B: Body,
73 {
74 #[pin]
75 parse_request: ParseRequest<B>,
76 service: S,
77 }
78}
79
80impl<B, S> Future for HandlerCallParseRequest<B, S>
81where
82 B: Body,
83 B::Error: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
84 S: Service<Event>,
85{
86 type Output = Result<S::Future>;
87
88 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
89 let s = self.project();
90 let event = match ready!(s.parse_request.poll(cx)) {
91 Ok(e) => e,
92 Err(e) => return Poll::Ready(Err(e)),
93 };
94 let call = s.service.call(event);
95 Poll::Ready(Ok(call))
96 }
97}
98
99pin_project! {
100 #[must_use]
101 #[project = HandlerCallServiceCallProject]
102 struct HandlerCallServiceCall<F> {
103 #[pin]
104 inner: F,
105 }
106}
107
108impl<F> Future for HandlerCallServiceCall<F>
109where
110 F: Future<Output = Result<(), Error>>,
111{
112 type Output = Result<Response<String>>;
113
114 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
115 let s = self.project();
116 if let Err(e) = ready!(s.inner.poll(cx)) {
117 return Poll::Ready(Err(e));
118 }
119 let res = Response::builder()
120 .status(StatusCode::NO_CONTENT)
121 .body(String::new())
122 .map_err(Error::handler);
123 Poll::Ready(res)
124 }
125}
126
127pin_project! {
128 #[must_use]
129 #[project = HandlerCallInnerProject]
130 #[project_replace = HandlerCallInnerProjectReplace]
131 enum HandlerCallInner<B, S>
132 where
133 B: Body,
134 S: Service<Event>,
135 {
136 ParseRequest {
137 #[pin]
138 inner: HandlerCallParseRequest<B, S>,
139 },
140 ServiceCall {
141 #[pin]
142 inner: HandlerCallServiceCall<S::Future>,
143 },
144 }
145}
146
147impl<B, S> Future for HandlerCallInner<B, S>
148where
149 B: Body,
150 B::Error: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
151 S: Service<Event, Response = (), Error = Error>,
152{
153 type Output = Result<Response<String>>;
154
155 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
156 let s = self.as_mut().project();
157 let service_call = match s {
158 HandlerCallInnerProject::ParseRequest { inner } => match ready!(inner.poll(cx)) {
159 Ok(c) => c,
160 Err(e) => return Poll::Ready(Err(e)),
161 },
162 HandlerCallInnerProject::ServiceCall { inner } => return inner.poll(cx),
163 };
164 self.project_replace(HandlerCallInner::ServiceCall {
165 inner: HandlerCallServiceCall {
166 inner: service_call,
167 },
168 });
169 cx.waker().wake_by_ref();
170 Poll::Pending
171 }
172}
173
174pin_project! {
175 #[must_use]
183 #[project = HandlerCallProject]
184 pub struct HandlerCall<B, S>
185 where
186 B: Body,
187 S: Service<Event>,
188 {
189 #[pin]
190 inner: HandlerCallInner<B, S>,
191 }
192}
193
194impl<B, S> HandlerCall<B, S>
195where
196 B: Body,
197 S: Service<Event>,
198{
199 pub(super) fn new(parse_request: ParseRequest<B>, service: S) -> Self {
200 Self {
201 inner: HandlerCallInner::ParseRequest {
202 inner: HandlerCallParseRequest {
203 parse_request,
204 service,
205 },
206 },
207 }
208 }
209}
210
211impl<B, S> Future for HandlerCall<B, S>
212where
213 B: Body,
214 B::Error: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
215 S: Service<Event, Response = (), Error = Error>,
216{
217 type Output = Result<Response<String>>;
218
219 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
220 let s = self.project();
221 s.inner.poll(cx)
222 }
223}