Skip to content

Commit b976ee6

Browse files
authored
Merge pull request #241 from H1rono/handler-call-future
✨ `HandlerCall`
2 parents b83191d + f631353 commit b976ee6

File tree

3 files changed

+255
-93
lines changed

3 files changed

+255
-93
lines changed

src/handler.rs

+17-73
Original file line numberDiff line numberDiff line change
@@ -7,58 +7,21 @@
77
88
use std::convert::Infallible;
99
use std::marker::PhantomData;
10-
use std::pin::Pin;
1110
use std::task::{Context, Poll};
1211

13-
use futures::future::{BoxFuture, Ready as ReadyFuture};
14-
use futures::ready;
15-
use http::{Request, Response, StatusCode};
12+
use futures::future::Ready as ReadyFuture;
13+
use http::{Request, Response};
1614
use paste::paste;
1715
use tower::Service;
1816

1917
use super::Handler;
2018
use crate::macros::all_events;
2119
use crate::{Error, Event, RequestParser};
2220

23-
pin_project_lite::pin_project! {
24-
/// <code>impl Future<Output = Result<(), [Error]>></code>
25-
///
26-
/// `F: Future<Output = Result<(), E>>`を受け取り、エラー型`E`を[`Error`]に変換した[`Future`]を返します。
27-
/// 以下のコードと同様です。
28-
///
29-
/// ```ignore
30-
/// use futures::{TryFutureExt};
31-
///
32-
/// async fn f() -> Result<(), E> { ... }
33-
///
34-
/// let wrap_error = f().map_err(|e| -> traq_bot_http::Error { ... });
35-
/// ```
36-
///
37-
/// [`Future`]: std::future::Future
38-
/// [`Error`]: crate::Error
39-
#[must_use]
40-
#[project = WrapErrorFutureProject]
41-
#[derive(Debug)]
42-
pub struct WrapErrorFuture<F, E> {
43-
_error: PhantomData<E>,
44-
#[pin]
45-
inner: F,
46-
}
47-
}
48-
49-
impl<F, E> std::future::Future for WrapErrorFuture<F, E>
50-
where
51-
F: std::future::Future<Output = Result<(), E>>,
52-
E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
53-
{
54-
type Output = crate::error::Result<()>;
21+
mod future;
5522

56-
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
57-
let s = self.project();
58-
let res = ready!(s.inner.poll(cx));
59-
Poll::Ready(res.map_err(Error::handler))
60-
}
61-
}
23+
#[allow(clippy::module_name_repetitions)]
24+
pub use future::{HandlerCall, WrapErrorFuture};
6225

6326
/// handleされなかった[`Event`]の受け皿となる[`Service`]です。
6427
///
@@ -195,27 +158,22 @@ impl<Service> Handler<Service> {
195158
/// 新しくイベントハンドラを作成します。`service`は以下の条件を満たす必要があります。
196159
///
197160
/// - <code>[Service]<[Event]></code>, [`Clone`]を実装している
198-
/// - [`'static`]
199161
/// - `Service::Response`が`()`と等しい
200162
/// - `Service::Error`が<code>Into<Box<dyn [Error] + [Send] + [Sync] + &#39;static>></code>を実装している
201-
/// - `Service::Future`が[`Send`]を実装している
202163
///
203164
/// [Service]: tower::Service
204165
/// [Event]: crate::Event
205166
/// [`Clone`]: std::clone::Clone
206-
/// [`'static`]: https://doc.rust-lang.org/rust-by-example/scope/lifetime/static_lifetime.html#trait-bound
207167
/// [Error]: std::error::Error
208168
/// [Send]: std::marker::Send
209169
/// [Sync]: std::marker::Sync
210-
/// [`Send`]: std::marker::Send
211170
pub fn new(parser: crate::RequestParser, service: Service) -> Self {
212171
Self { service, parser }
213172
}
214173

215174
/// イベントハンドラに`State`を追加します。`State`は以下の条件を満たす必要があります。
216175
///
217-
/// - [`Clone`], [`Send`]を実装している
218-
/// - [`'static`]
176+
/// - [`Clone`]を実装している
219177
///
220178
/// # Example
221179
///
@@ -241,8 +199,6 @@ impl<Service> Handler<Service> {
241199
/// ```
242200
///
243201
/// [`Clone`]: std::clone::Clone
244-
/// [`Send`]: std::marker::Send
245-
/// [`'static`]: https://doc.rust-lang.org/rust-by-example/scope/lifetime/static_lifetime.html#trait-bound
246202
pub fn with_state<State>(self, state: State) -> Handler<WithState<State, Service>> {
247203
let Self { service, parser } = self;
248204
Handler {
@@ -269,24 +225,22 @@ macro_rules! all_handler_on_events {
269225
#[doc = paste! { concat!(
270226
"[`", stringify!([< $e:camel Payload >]), "`]をhandleする[`Service`]を登録します。\n\n",
271227
"引数の型`Service2`は`Service<Req>` traitを実装し、さらに以下の条件を満たす必要があります。\n\n",
272-
"- [`Clone`], [`Send`]を実装している\n",
273-
"- [`'static`]\n",
228+
"- [`Clone`]を実装している\n",
274229
"- `Req`が次のうちいずれかと等しい\n",
275230
" - [`", stringify!([< $e:camel Payload >]), "`]\n",
276231
" - `(", stringify!([< $e:camel Payload >]), ",)`\n",
277232
" - `(State, ", stringify!([< $e:camel Payload >]), ")` ",
278233
"(`State`に関しては[`Handler::with_state`]を参照してください)\n",
279234
"- `Service2::Response`が`()`と等しい\n",
280-
"- `Service2::Error`が<code>Into<Box<dyn [Error] + Send + Sync + &#39;static>></code>を実装している\n",
281-
"- `Service2::Future`が[`Send`]を実装している\n\n",
235+
"- `Service2::Error`が<code>Into<Box<dyn [Error] + [Send] + [Sync] + &#39;static>></code>を実装している\n\n",
282236
"[`Service`]: tower::Service\n",
283237
"[`", stringify!([< $e:camel Payload >]), "`]: ",
284238
"crate::payloads::", stringify!([< $e:camel Payload >]), "\n",
285239
"[`Clone`]: std::clone::Clone\n",
286-
"[`Send`]: std::marker::Send\n",
287-
"[`'static`]: https://doc.rust-lang.org/rust-by-example/scope/lifetime/static_lifetime.html#trait-bound\n",
288240
"[`Handler::with_state`]: crate::Handler::with_state\n",
289241
"[Error]: std::error::Error\n",
242+
"[Send]: std::marker::Send\n",
243+
"[Sync]: std::marker::Sync\n",
290244
)}]
291245
pub $e;
292246
)* }
@@ -297,35 +251,25 @@ all_events! {all_handler_on_events}
297251

298252
impl<Srv, Body> Service<Request<Body>> for Handler<Srv>
299253
where
300-
Srv: Service<Event, Response = ()> + Send + 'static,
254+
Srv: Service<Event, Response = ()>,
301255
Srv: Clone,
302256
Srv::Error: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
303-
Srv::Future: Send,
304-
Body: http_body::Body + Send + 'static,
305-
Body::Data: Send,
257+
Body: http_body::Body,
306258
Body::Error: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
307259
{
308260
type Response = Response<String>;
309261
type Error = Error;
310-
type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
262+
type Future = HandlerCall<Body, Srv>;
311263

312264
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
313265
self.service.poll_ready(cx).map_err(Error::handler)
314266
}
315267

316268
fn call(&mut self, req: Request<Body>) -> Self::Future {
317-
// FIXME: このclone消せる
318-
// req.parts.headersからEventKindはasyncなしに判定できるので
319-
let mut s = self.clone();
269+
let parse_request = self.parser.parse_request(req);
270+
let mut s = self.service.clone();
320271
// https://docs.rs/tower/latest/tower/trait.Service.html#be-careful-when-cloning-inner-services
321-
std::mem::swap(self, &mut s);
322-
Box::pin(async move {
323-
let event = s.parser.parse_request(req).await?;
324-
s.service.call(event).await.map_err(Error::handler)?;
325-
Response::builder()
326-
.status(StatusCode::NO_CONTENT)
327-
.body(String::new())
328-
.map_err(Error::handler)
329-
})
272+
std::mem::swap(&mut self.service, &mut s);
273+
HandlerCall::new(parse_request, s)
330274
}
331275
}

0 commit comments

Comments
 (0)