1
0
mirror of https://github.com/fafhrd91/actix-web synced 2025-01-31 11:02:08 +01:00
actix-web/src/with.rs

384 lines
10 KiB
Rust
Raw Normal View History

2018-04-13 16:02:01 -07:00
use futures::{Async, Future, Poll};
2018-03-26 23:10:31 -07:00
use std::marker::PhantomData;
2018-04-13 16:02:01 -07:00
use std::rc::Rc;
2018-03-26 23:10:31 -07:00
use error::Error;
2018-05-03 16:22:08 -07:00
use handler::{AsyncResult, AsyncResultItem, FromRequest, Handler, Responder};
2018-03-26 23:10:31 -07:00
use httprequest::HttpRequest;
use httpresponse::HttpResponse;
trait FnWith<T, R>: 'static {
fn call_with(self: &Self, T) -> R;
}
impl<T, R, F: Fn(T) -> R + 'static> FnWith<T, R> for F {
fn call_with(self: &Self, arg: T) -> R {
(*self)(arg)
}
}
#[doc(hidden)]
pub trait WithFactory<T, S, R>: 'static
2018-08-23 09:48:01 -07:00
where
T: FromRequest<S>,
R: Responder,
{
fn create(self) -> With<T, S, R>;
fn create_with_config(self, T::Config) -> With<T, S, R>;
}
#[doc(hidden)]
pub trait WithAsyncFactory<T, S, R, I, E>: 'static
2018-08-23 09:48:01 -07:00
where
T: FromRequest<S>,
R: Future<Item = I, Error = E>,
I: Responder,
E: Into<Error>,
{
fn create(self) -> WithAsync<T, S, R, I, E>;
fn create_with_config(self, T::Config) -> WithAsync<T, S, R, I, E>;
}
#[doc(hidden)]
pub struct With<T, S, R>
2018-04-13 16:02:01 -07:00
where
T: FromRequest<S>,
S: 'static,
2018-03-26 23:10:31 -07:00
{
hnd: Rc<FnWith<T, R>>,
2018-06-21 11:47:01 +06:00
cfg: Rc<T::Config>,
2018-03-31 09:58:33 -07:00
_s: PhantomData<S>,
2018-03-26 23:10:31 -07:00
}
impl<T, S, R> With<T, S, R>
2018-04-13 16:02:01 -07:00
where
T: FromRequest<S>,
S: 'static,
2018-03-26 23:10:31 -07:00
{
pub fn new<F: Fn(T) -> R + 'static>(f: F, cfg: T::Config) -> Self {
2018-04-13 16:02:01 -07:00
With {
2018-06-21 11:47:01 +06:00
cfg: Rc::new(cfg),
2018-06-21 23:21:28 +06:00
hnd: Rc::new(f),
_s: PhantomData,
2018-04-13 16:02:01 -07:00
}
2018-03-26 23:10:31 -07:00
}
}
impl<T, S, R> Handler<S> for With<T, S, R>
2018-04-13 16:02:01 -07:00
where
R: Responder + 'static,
T: FromRequest<S> + 'static,
S: 'static,
2018-03-26 23:10:31 -07:00
{
2018-05-03 16:22:08 -07:00
type Result = AsyncResult<HttpResponse>;
2018-03-26 23:10:31 -07:00
2018-06-25 10:58:04 +06:00
fn handle(&self, req: &HttpRequest<S>) -> Self::Result {
2018-04-13 16:02:01 -07:00
let mut fut = WithHandlerFut {
2018-06-25 10:58:04 +06:00
req: req.clone(),
2018-03-29 09:26:01 -07:00
started: false,
hnd: Rc::clone(&self.hnd),
2018-04-03 22:06:18 -07:00
cfg: self.cfg.clone(),
2018-03-29 09:26:01 -07:00
fut1: None,
fut2: None,
};
match fut.poll() {
2018-05-03 16:22:08 -07:00
Ok(Async::Ready(resp)) => AsyncResult::ok(resp),
Ok(Async::NotReady) => AsyncResult::async(Box::new(fut)),
2018-05-04 11:44:22 -07:00
Err(e) => AsyncResult::err(e),
}
2018-03-26 23:10:31 -07:00
}
}
struct WithHandlerFut<T, S, R>
2018-04-13 16:02:01 -07:00
where
R: Responder,
T: FromRequest<S> + 'static,
S: 'static,
2018-03-26 23:10:31 -07:00
{
2018-03-29 09:26:01 -07:00
started: bool,
hnd: Rc<FnWith<T, R>>,
2018-06-21 11:47:01 +06:00
cfg: Rc<T::Config>,
2018-03-26 23:10:31 -07:00
req: HttpRequest<S>,
2018-04-13 16:02:01 -07:00
fut1: Option<Box<Future<Item = T, Error = Error>>>,
fut2: Option<Box<Future<Item = HttpResponse, Error = Error>>>,
2018-03-26 23:10:31 -07:00
}
impl<T, S, R> Future for WithHandlerFut<T, S, R>
2018-04-13 16:02:01 -07:00
where
R: Responder + 'static,
T: FromRequest<S> + 'static,
S: 'static,
2018-03-26 23:10:31 -07:00
{
type Item = HttpResponse;
type Error = Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if let Some(ref mut fut) = self.fut2 {
2018-04-13 16:02:01 -07:00
return fut.poll();
2018-03-26 23:10:31 -07:00
}
2018-03-29 09:26:01 -07:00
let item = if !self.started {
self.started = true;
let reply = T::from_request(&self.req, self.cfg.as_ref()).into();
2018-05-01 17:19:15 -07:00
match reply.into() {
2018-05-03 16:22:08 -07:00
AsyncResultItem::Err(err) => return Err(err),
AsyncResultItem::Ok(msg) => msg,
AsyncResultItem::Future(fut) => {
2018-05-01 17:19:15 -07:00
self.fut1 = Some(fut);
return self.poll();
2018-04-13 16:02:01 -07:00
}
2018-03-29 09:26:01 -07:00
}
} else {
match self.fut1.as_mut().unwrap().poll()? {
Async::Ready(item) => item,
Async::NotReady => return Ok(Async::NotReady),
}
2018-03-26 23:10:31 -07:00
};
let item = match self.hnd.as_ref().call_with(item).respond_to(&self.req) {
2018-06-21 23:21:28 +06:00
Ok(item) => item.into(),
Err(e) => return Err(e.into()),
};
2018-03-26 23:10:31 -07:00
2018-06-21 23:21:28 +06:00
match item.into() {
AsyncResultItem::Err(err) => Err(err),
AsyncResultItem::Ok(resp) => Ok(Async::Ready(resp)),
AsyncResultItem::Future(fut) => {
self.fut2 = Some(fut);
self.poll()
2018-03-31 09:58:33 -07:00
}
2018-06-21 23:21:28 +06:00
}
2018-03-26 23:10:31 -07:00
}
}
2018-03-28 14:24:32 -07:00
#[doc(hidden)]
pub struct WithAsync<T, S, R, I, E>
where
R: Future<Item = I, Error = E>,
I: Responder,
E: Into<E>,
T: FromRequest<S>,
S: 'static,
{
hnd: Rc<FnWith<T, R>>,
2018-06-21 11:47:01 +06:00
cfg: Rc<T::Config>,
2018-06-21 23:21:28 +06:00
_s: PhantomData<S>,
}
impl<T, S, R, I, E> WithAsync<T, S, R, I, E>
where
R: Future<Item = I, Error = E>,
I: Responder,
E: Into<Error>,
T: FromRequest<S>,
S: 'static,
{
pub fn new<F: Fn(T) -> R + 'static>(f: F, cfg: T::Config) -> Self {
WithAsync {
2018-06-21 11:47:01 +06:00
cfg: Rc::new(cfg),
2018-06-21 23:21:28 +06:00
hnd: Rc::new(f),
_s: PhantomData,
}
}
}
impl<T, S, R, I, E> Handler<S> for WithAsync<T, S, R, I, E>
where
R: Future<Item = I, Error = E> + 'static,
I: Responder + 'static,
E: Into<Error> + 'static,
T: FromRequest<S> + 'static,
S: 'static,
{
type Result = AsyncResult<HttpResponse>;
2018-06-25 10:58:04 +06:00
fn handle(&self, req: &HttpRequest<S>) -> Self::Result {
let mut fut = WithAsyncHandlerFut {
2018-06-25 10:58:04 +06:00
req: req.clone(),
started: false,
hnd: Rc::clone(&self.hnd),
2018-06-21 11:47:01 +06:00
cfg: Rc::clone(&self.cfg),
fut1: None,
fut2: None,
fut3: None,
};
match fut.poll() {
Ok(Async::Ready(resp)) => AsyncResult::ok(resp),
Ok(Async::NotReady) => AsyncResult::async(Box::new(fut)),
Err(e) => AsyncResult::err(e),
}
}
}
struct WithAsyncHandlerFut<T, S, R, I, E>
where
R: Future<Item = I, Error = E> + 'static,
I: Responder + 'static,
E: Into<Error> + 'static,
T: FromRequest<S> + 'static,
S: 'static,
{
started: bool,
hnd: Rc<FnWith<T, R>>,
2018-06-21 11:47:01 +06:00
cfg: Rc<T::Config>,
req: HttpRequest<S>,
fut1: Option<Box<Future<Item = T, Error = Error>>>,
fut2: Option<R>,
fut3: Option<Box<Future<Item = HttpResponse, Error = Error>>>,
}
impl<T, S, R, I, E> Future for WithAsyncHandlerFut<T, S, R, I, E>
where
R: Future<Item = I, Error = E> + 'static,
I: Responder + 'static,
E: Into<Error> + 'static,
T: FromRequest<S> + 'static,
S: 'static,
{
type Item = HttpResponse;
type Error = Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if let Some(ref mut fut) = self.fut3 {
return fut.poll();
}
if self.fut2.is_some() {
return match self.fut2.as_mut().unwrap().poll() {
Ok(Async::NotReady) => Ok(Async::NotReady),
Ok(Async::Ready(r)) => match r.respond_to(&self.req) {
Ok(r) => match r.into().into() {
AsyncResultItem::Err(err) => Err(err),
AsyncResultItem::Ok(resp) => Ok(Async::Ready(resp)),
AsyncResultItem::Future(fut) => {
self.fut3 = Some(fut);
self.poll()
}
},
Err(e) => Err(e.into()),
},
Err(e) => Err(e.into()),
};
}
let item = if !self.started {
self.started = true;
let reply = T::from_request(&self.req, self.cfg.as_ref()).into();
match reply.into() {
AsyncResultItem::Err(err) => return Err(err),
AsyncResultItem::Ok(msg) => msg,
AsyncResultItem::Future(fut) => {
self.fut1 = Some(fut);
return self.poll();
}
}
} else {
match self.fut1.as_mut().unwrap().poll()? {
Async::Ready(item) => item,
Async::NotReady => return Ok(Async::NotReady),
}
};
self.fut2 = Some(self.hnd.as_ref().call_with(item));
self.poll()
}
}
macro_rules! with_factory_tuple ({$(($n:tt, $T:ident)),+} => {
impl<$($T,)+ State, Func, Res> WithFactory<($($T,)+), State, Res> for Func
where Func: Fn($($T,)+) -> Res + 'static,
$($T: FromRequest<State> + 'static,)+
Res: Responder + 'static,
State: 'static,
{
fn create(self) -> With<($($T,)+), State, Res> {
With::new(move |($($n,)+)| (self)($($n,)+), ($($T::Config::default(),)+))
}
fn create_with_config(self, cfg: ($($T::Config,)+)) -> With<($($T,)+), State, Res> {
With::new(move |($($n,)+)| (self)($($n,)+), cfg)
}
}
});
macro_rules! with_async_factory_tuple ({$(($n:tt, $T:ident)),+} => {
impl<$($T,)+ State, Func, Res, Item, Err> WithAsyncFactory<($($T,)+), State, Res, Item, Err> for Func
where Func: Fn($($T,)+) -> Res + 'static,
$($T: FromRequest<State> + 'static,)+
Res: Future<Item=Item, Error=Err>,
Item: Responder + 'static,
Err: Into<Error>,
State: 'static,
{
fn create(self) -> WithAsync<($($T,)+), State, Res, Item, Err> {
WithAsync::new(move |($($n,)+)| (self)($($n,)+), ($($T::Config::default(),)+))
}
fn create_with_config(self, cfg: ($($T::Config,)+)) -> WithAsync<($($T,)+), State, Res, Item, Err> {
WithAsync::new(move |($($n,)+)| (self)($($n,)+), cfg)
}
}
});
with_factory_tuple!((a, A));
with_factory_tuple!((a, A), (b, B));
with_factory_tuple!((a, A), (b, B), (c, C));
with_factory_tuple!((a, A), (b, B), (c, C), (d, D));
with_factory_tuple!((a, A), (b, B), (c, C), (d, D), (e, E));
with_factory_tuple!((a, A), (b, B), (c, C), (d, D), (e, E), (f, F));
with_factory_tuple!((a, A), (b, B), (c, C), (d, D), (e, E), (f, F), (g, G));
2018-08-23 09:48:01 -07:00
with_factory_tuple!(
(a, A),
(b, B),
(c, C),
(d, D),
(e, E),
(f, F),
(g, G),
(h, H)
);
with_factory_tuple!(
(a, A),
(b, B),
(c, C),
(d, D),
(e, E),
(f, F),
(g, G),
(h, H),
(i, I)
);
with_async_factory_tuple!((a, A));
with_async_factory_tuple!((a, A), (b, B));
with_async_factory_tuple!((a, A), (b, B), (c, C));
with_async_factory_tuple!((a, A), (b, B), (c, C), (d, D));
with_async_factory_tuple!((a, A), (b, B), (c, C), (d, D), (e, E));
with_async_factory_tuple!((a, A), (b, B), (c, C), (d, D), (e, E), (f, F));
with_async_factory_tuple!((a, A), (b, B), (c, C), (d, D), (e, E), (f, F), (g, G));
2018-08-23 09:48:01 -07:00
with_async_factory_tuple!(
(a, A),
(b, B),
(c, C),
(d, D),
(e, E),
(f, F),
(g, G),
(h, H)
);
with_async_factory_tuple!(
(a, A),
(b, B),
(c, C),
(d, D),
(e, E),
(f, F),
(g, G),
(h, H),
(i, I)
);