2018-04-14 01:02:01 +02:00
|
|
|
use futures::{Async, Future, Poll};
|
2018-03-27 08:10:31 +02:00
|
|
|
use std::cell::UnsafeCell;
|
|
|
|
use std::marker::PhantomData;
|
2018-04-04 07:06:18 +02:00
|
|
|
use std::ops::{Deref, DerefMut};
|
2018-04-14 01:02:01 +02:00
|
|
|
use std::rc::Rc;
|
2018-03-27 08:10:31 +02:00
|
|
|
|
|
|
|
use error::Error;
|
2018-04-14 01:02:01 +02:00
|
|
|
use handler::{FromRequest, Handler, Reply, ReplyItem, Responder};
|
2018-03-27 08:10:31 +02:00
|
|
|
use httprequest::HttpRequest;
|
|
|
|
use httpresponse::HttpResponse;
|
|
|
|
|
2018-04-04 07:06:18 +02:00
|
|
|
pub struct ExtractorConfig<S: 'static, T: FromRequest<S>> {
|
2018-04-14 01:02:01 +02:00
|
|
|
cfg: Rc<UnsafeCell<T::Config>>,
|
2018-04-04 07:06:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<S: 'static, T: FromRequest<S>> Default for ExtractorConfig<S, T> {
|
|
|
|
fn default() -> Self {
|
2018-04-14 01:02:01 +02:00
|
|
|
ExtractorConfig {
|
|
|
|
cfg: Rc::new(UnsafeCell::new(T::Config::default())),
|
|
|
|
}
|
2018-04-04 07:06:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<S: 'static, T: FromRequest<S>> Clone for ExtractorConfig<S, T> {
|
|
|
|
fn clone(&self) -> Self {
|
2018-04-14 01:02:01 +02:00
|
|
|
ExtractorConfig {
|
|
|
|
cfg: Rc::clone(&self.cfg),
|
|
|
|
}
|
2018-04-04 07:06:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<S: 'static, T: FromRequest<S>> AsRef<T::Config> for ExtractorConfig<S, T> {
|
|
|
|
fn as_ref(&self) -> &T::Config {
|
2018-04-14 01:02:01 +02:00
|
|
|
unsafe { &*self.cfg.get() }
|
2018-04-04 07:06:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<S: 'static, T: FromRequest<S>> Deref for ExtractorConfig<S, T> {
|
|
|
|
type Target = T::Config;
|
|
|
|
|
|
|
|
fn deref(&self) -> &T::Config {
|
2018-04-14 01:02:01 +02:00
|
|
|
unsafe { &*self.cfg.get() }
|
2018-04-04 07:06:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<S: 'static, T: FromRequest<S>> DerefMut for ExtractorConfig<S, T> {
|
|
|
|
fn deref_mut(&mut self) -> &mut T::Config {
|
2018-04-14 01:02:01 +02:00
|
|
|
unsafe { &mut *self.cfg.get() }
|
2018-04-04 07:06:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-31 18:58:33 +02:00
|
|
|
pub struct With<T, S, F, R>
|
2018-04-14 01:02:01 +02:00
|
|
|
where
|
|
|
|
F: Fn(T) -> R,
|
|
|
|
T: FromRequest<S>,
|
|
|
|
S: 'static,
|
2018-03-27 08:10:31 +02:00
|
|
|
{
|
2018-03-31 18:58:33 +02:00
|
|
|
hnd: Rc<UnsafeCell<F>>,
|
2018-04-04 07:06:18 +02:00
|
|
|
cfg: ExtractorConfig<S, T>,
|
2018-03-31 18:58:33 +02:00
|
|
|
_s: PhantomData<S>,
|
2018-03-27 08:10:31 +02:00
|
|
|
}
|
|
|
|
|
2018-03-31 18:58:33 +02:00
|
|
|
impl<T, S, F, R> With<T, S, F, R>
|
2018-04-14 01:02:01 +02:00
|
|
|
where
|
|
|
|
F: Fn(T) -> R,
|
|
|
|
T: FromRequest<S>,
|
|
|
|
S: 'static,
|
2018-03-27 08:10:31 +02:00
|
|
|
{
|
2018-04-04 07:06:18 +02:00
|
|
|
pub fn new(f: F, cfg: ExtractorConfig<S, T>) -> Self {
|
2018-04-14 01:02:01 +02:00
|
|
|
With {
|
|
|
|
cfg,
|
|
|
|
hnd: Rc::new(UnsafeCell::new(f)),
|
|
|
|
_s: PhantomData,
|
|
|
|
}
|
2018-03-27 08:10:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-31 18:58:33 +02:00
|
|
|
impl<T, S, F, R> Handler<S> for With<T, S, F, R>
|
2018-04-14 01:02:01 +02:00
|
|
|
where
|
|
|
|
F: Fn(T) -> R + 'static,
|
|
|
|
R: Responder + 'static,
|
|
|
|
T: FromRequest<S> + 'static,
|
|
|
|
S: 'static,
|
2018-03-27 08:10:31 +02:00
|
|
|
{
|
2018-05-02 02:19:15 +02:00
|
|
|
type Result = Reply<HttpResponse>;
|
2018-03-27 08:10:31 +02:00
|
|
|
|
|
|
|
fn handle(&mut self, req: HttpRequest<S>) -> Self::Result {
|
2018-04-14 01:02:01 +02:00
|
|
|
let mut fut = WithHandlerFut {
|
2018-03-29 18:26:01 +02:00
|
|
|
req,
|
|
|
|
started: false,
|
|
|
|
hnd: Rc::clone(&self.hnd),
|
2018-04-04 07:06:18 +02:00
|
|
|
cfg: self.cfg.clone(),
|
2018-03-29 18:26:01 +02:00
|
|
|
fut1: None,
|
|
|
|
fut2: None,
|
|
|
|
};
|
|
|
|
|
2018-03-29 06:33:40 +02:00
|
|
|
match fut.poll() {
|
2018-03-29 18:26:01 +02:00
|
|
|
Ok(Async::Ready(resp)) => Reply::response(resp),
|
|
|
|
Ok(Async::NotReady) => Reply::async(fut),
|
2018-05-02 02:19:15 +02:00
|
|
|
Err(e) => Reply::error::<Error>(e),
|
2018-03-29 06:33:40 +02:00
|
|
|
}
|
2018-03-27 08:10:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-31 18:58:33 +02:00
|
|
|
struct WithHandlerFut<T, S, F, R>
|
2018-04-14 01:02:01 +02:00
|
|
|
where
|
|
|
|
F: Fn(T) -> R,
|
|
|
|
R: Responder,
|
|
|
|
T: FromRequest<S> + 'static,
|
|
|
|
S: 'static,
|
2018-03-27 08:10:31 +02:00
|
|
|
{
|
2018-03-29 18:26:01 +02:00
|
|
|
started: bool,
|
2018-03-31 18:58:33 +02:00
|
|
|
hnd: Rc<UnsafeCell<F>>,
|
2018-04-04 07:06:18 +02:00
|
|
|
cfg: ExtractorConfig<S, T>,
|
2018-03-27 08:10:31 +02:00
|
|
|
req: HttpRequest<S>,
|
2018-04-14 01:02:01 +02:00
|
|
|
fut1: Option<Box<Future<Item = T, Error = Error>>>,
|
|
|
|
fut2: Option<Box<Future<Item = HttpResponse, Error = Error>>>,
|
2018-03-27 08:10:31 +02:00
|
|
|
}
|
|
|
|
|
2018-03-31 18:58:33 +02:00
|
|
|
impl<T, S, F, R> Future for WithHandlerFut<T, S, F, R>
|
2018-04-14 01:02:01 +02:00
|
|
|
where
|
|
|
|
F: Fn(T) -> R,
|
|
|
|
R: Responder + 'static,
|
|
|
|
T: FromRequest<S> + 'static,
|
|
|
|
S: 'static,
|
2018-03-27 08:10:31 +02: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-14 01:02:01 +02:00
|
|
|
return fut.poll();
|
2018-03-27 08:10:31 +02:00
|
|
|
}
|
|
|
|
|
2018-03-29 18:26:01 +02:00
|
|
|
let item = if !self.started {
|
|
|
|
self.started = true;
|
2018-05-02 15:07:30 +02:00
|
|
|
let reply = T::from_request(&self.req, self.cfg.as_ref()).into();
|
2018-05-02 02:19:15 +02:00
|
|
|
match reply.into() {
|
|
|
|
ReplyItem::Error(err) => return Err(err),
|
|
|
|
ReplyItem::Message(msg) => msg,
|
|
|
|
ReplyItem::Future(fut) => {
|
|
|
|
self.fut1 = Some(fut);
|
|
|
|
return self.poll();
|
2018-04-14 01:02:01 +02:00
|
|
|
}
|
2018-05-02 02:30:06 +02:00
|
|
|
ReplyItem::None => panic!("use after resolve"),
|
2018-03-29 18:26:01 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
match self.fut1.as_mut().unwrap().poll()? {
|
|
|
|
Async::Ready(item) => item,
|
|
|
|
Async::NotReady => return Ok(Async::NotReady),
|
|
|
|
}
|
2018-03-27 08:10:31 +02:00
|
|
|
};
|
|
|
|
|
2018-04-14 01:02:01 +02:00
|
|
|
let hnd: &mut F = unsafe { &mut *self.hnd.get() };
|
2018-04-11 21:27:17 +02:00
|
|
|
let item = match (*hnd)(item).respond_to(self.req.drop_state()) {
|
2018-03-27 08:10:31 +02:00
|
|
|
Ok(item) => item.into(),
|
2018-03-31 18:58:33 +02:00
|
|
|
Err(e) => return Err(e.into()),
|
2018-03-27 08:10:31 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
match item.into() {
|
2018-05-02 02:19:15 +02:00
|
|
|
ReplyItem::Error(err) => Err(err),
|
2018-03-31 18:58:33 +02:00
|
|
|
ReplyItem::Message(resp) => Ok(Async::Ready(resp)),
|
|
|
|
ReplyItem::Future(fut) => {
|
|
|
|
self.fut2 = Some(fut);
|
|
|
|
self.poll()
|
|
|
|
}
|
2018-05-02 02:30:06 +02:00
|
|
|
ReplyItem::None => panic!("use after resolve"),
|
2018-03-27 08:10:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-03-28 23:24:32 +02:00
|
|
|
|
2018-04-04 07:06:18 +02:00
|
|
|
pub struct With2<T1, T2, S, F, R>
|
2018-04-14 01:02:01 +02:00
|
|
|
where
|
|
|
|
F: Fn(T1, T2) -> R,
|
|
|
|
T1: FromRequest<S> + 'static,
|
|
|
|
T2: FromRequest<S> + 'static,
|
|
|
|
S: 'static,
|
2018-03-28 23:24:32 +02:00
|
|
|
{
|
|
|
|
hnd: Rc<UnsafeCell<F>>,
|
2018-04-04 07:06:18 +02:00
|
|
|
cfg1: ExtractorConfig<S, T1>,
|
|
|
|
cfg2: ExtractorConfig<S, T2>,
|
2018-03-28 23:24:32 +02:00
|
|
|
_s: PhantomData<S>,
|
|
|
|
}
|
|
|
|
|
2018-04-04 07:06:18 +02:00
|
|
|
impl<T1, T2, S, F, R> With2<T1, T2, S, F, R>
|
2018-04-14 01:02:01 +02:00
|
|
|
where
|
|
|
|
F: Fn(T1, T2) -> R,
|
|
|
|
T1: FromRequest<S> + 'static,
|
|
|
|
T2: FromRequest<S> + 'static,
|
|
|
|
S: 'static,
|
2018-03-31 18:58:33 +02:00
|
|
|
{
|
2018-04-14 01:02:01 +02:00
|
|
|
pub fn new(
|
2018-04-29 07:55:47 +02:00
|
|
|
f: F, cfg1: ExtractorConfig<S, T1>, cfg2: ExtractorConfig<S, T2>,
|
2018-04-14 01:02:01 +02:00
|
|
|
) -> Self {
|
|
|
|
With2 {
|
|
|
|
hnd: Rc::new(UnsafeCell::new(f)),
|
|
|
|
cfg1,
|
|
|
|
cfg2,
|
|
|
|
_s: PhantomData,
|
|
|
|
}
|
2018-03-31 18:58:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-28 23:24:32 +02:00
|
|
|
impl<T1, T2, S, F, R> Handler<S> for With2<T1, T2, S, F, R>
|
2018-04-14 01:02:01 +02:00
|
|
|
where
|
|
|
|
F: Fn(T1, T2) -> R + 'static,
|
|
|
|
R: Responder + 'static,
|
|
|
|
T1: FromRequest<S> + 'static,
|
|
|
|
T2: FromRequest<S> + 'static,
|
|
|
|
S: 'static,
|
2018-03-28 23:24:32 +02:00
|
|
|
{
|
2018-05-02 02:19:15 +02:00
|
|
|
type Result = Reply<HttpResponse>;
|
2018-03-28 23:24:32 +02:00
|
|
|
|
|
|
|
fn handle(&mut self, req: HttpRequest<S>) -> Self::Result {
|
2018-04-14 01:02:01 +02:00
|
|
|
let mut fut = WithHandlerFut2 {
|
2018-03-29 18:26:01 +02:00
|
|
|
req,
|
|
|
|
started: false,
|
|
|
|
hnd: Rc::clone(&self.hnd),
|
2018-04-04 07:06:18 +02:00
|
|
|
cfg1: self.cfg1.clone(),
|
|
|
|
cfg2: self.cfg2.clone(),
|
2018-03-29 18:26:01 +02:00
|
|
|
item: None,
|
|
|
|
fut1: None,
|
|
|
|
fut2: None,
|
|
|
|
fut3: None,
|
|
|
|
};
|
2018-03-29 06:33:40 +02:00
|
|
|
match fut.poll() {
|
2018-03-29 18:26:01 +02:00
|
|
|
Ok(Async::Ready(resp)) => Reply::response(resp),
|
|
|
|
Ok(Async::NotReady) => Reply::async(fut),
|
2018-03-29 06:33:40 +02:00
|
|
|
Err(e) => Reply::response(e),
|
|
|
|
}
|
2018-03-28 23:24:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct WithHandlerFut2<T1, T2, S, F, R>
|
2018-04-14 01:02:01 +02:00
|
|
|
where
|
|
|
|
F: Fn(T1, T2) -> R + 'static,
|
|
|
|
R: Responder + 'static,
|
|
|
|
T1: FromRequest<S> + 'static,
|
|
|
|
T2: FromRequest<S> + 'static,
|
|
|
|
S: 'static,
|
2018-03-28 23:24:32 +02:00
|
|
|
{
|
2018-03-29 18:26:01 +02:00
|
|
|
started: bool,
|
2018-03-28 23:24:32 +02:00
|
|
|
hnd: Rc<UnsafeCell<F>>,
|
2018-04-04 07:06:18 +02:00
|
|
|
cfg1: ExtractorConfig<S, T1>,
|
|
|
|
cfg2: ExtractorConfig<S, T2>,
|
2018-03-28 23:24:32 +02:00
|
|
|
req: HttpRequest<S>,
|
|
|
|
item: Option<T1>,
|
2018-04-14 01:02:01 +02:00
|
|
|
fut1: Option<Box<Future<Item = T1, Error = Error>>>,
|
|
|
|
fut2: Option<Box<Future<Item = T2, Error = Error>>>,
|
|
|
|
fut3: Option<Box<Future<Item = HttpResponse, Error = Error>>>,
|
2018-03-28 23:24:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T1, T2, S, F, R> Future for WithHandlerFut2<T1, T2, S, F, R>
|
2018-04-14 01:02:01 +02:00
|
|
|
where
|
|
|
|
F: Fn(T1, T2) -> R + 'static,
|
|
|
|
R: Responder + 'static,
|
|
|
|
T1: FromRequest<S> + 'static,
|
|
|
|
T2: FromRequest<S> + 'static,
|
|
|
|
S: 'static,
|
2018-03-28 23:24:32 +02:00
|
|
|
{
|
|
|
|
type Item = HttpResponse;
|
|
|
|
type Error = Error;
|
|
|
|
|
|
|
|
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
|
|
|
if let Some(ref mut fut) = self.fut3 {
|
2018-04-14 01:02:01 +02:00
|
|
|
return fut.poll();
|
2018-03-28 23:24:32 +02:00
|
|
|
}
|
|
|
|
|
2018-03-29 18:26:01 +02:00
|
|
|
if !self.started {
|
|
|
|
self.started = true;
|
2018-05-02 15:07:30 +02:00
|
|
|
let reply = T1::from_request(&self.req, self.cfg1.as_ref()).into();
|
2018-05-02 02:19:15 +02:00
|
|
|
let item1 = match reply.into() {
|
|
|
|
ReplyItem::Error(err) => return Err(err),
|
|
|
|
ReplyItem::Message(msg) => msg,
|
|
|
|
ReplyItem::Future(fut) => {
|
|
|
|
self.fut1 = Some(fut);
|
|
|
|
return self.poll();
|
2018-04-14 01:02:01 +02:00
|
|
|
}
|
2018-05-02 02:30:06 +02:00
|
|
|
ReplyItem::None => panic!("use after resolve"),
|
2018-05-02 02:19:15 +02:00
|
|
|
};
|
|
|
|
|
2018-05-02 15:07:30 +02:00
|
|
|
let reply = T2::from_request(&self.req, self.cfg2.as_ref()).into();
|
2018-05-02 02:19:15 +02:00
|
|
|
let item2 = match reply.into() {
|
|
|
|
ReplyItem::Error(err) => return Err(err),
|
|
|
|
ReplyItem::Message(msg) => msg,
|
|
|
|
ReplyItem::Future(fut) => {
|
|
|
|
self.item = Some(item1);
|
|
|
|
self.fut2 = Some(fut);
|
|
|
|
return self.poll();
|
2018-03-29 18:26:01 +02:00
|
|
|
}
|
2018-05-02 02:30:06 +02:00
|
|
|
ReplyItem::None => panic!("use after resolve"),
|
2018-05-02 02:19:15 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
let hnd: &mut F = unsafe { &mut *self.hnd.get() };
|
|
|
|
match (*hnd)(item1, item2).respond_to(self.req.drop_state()) {
|
|
|
|
Ok(item) => match item.into().into() {
|
|
|
|
ReplyItem::Error(err) => return Err(err),
|
|
|
|
ReplyItem::Message(resp) => return Ok(Async::Ready(resp)),
|
|
|
|
ReplyItem::Future(fut) => {
|
|
|
|
self.fut3 = Some(fut);
|
|
|
|
return self.poll();
|
|
|
|
}
|
2018-05-02 02:30:06 +02:00
|
|
|
ReplyItem::None => panic!("use after resolve"),
|
2018-05-02 02:19:15 +02:00
|
|
|
},
|
|
|
|
Err(e) => return Err(e.into()),
|
2018-03-29 18:26:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-28 23:24:32 +02:00
|
|
|
if self.fut1.is_some() {
|
|
|
|
match self.fut1.as_mut().unwrap().poll()? {
|
|
|
|
Async::Ready(item) => {
|
2018-05-02 15:07:30 +02:00
|
|
|
let reply = T2::from_request(&self.req, self.cfg2.as_ref()).into();
|
2018-05-02 02:19:15 +02:00
|
|
|
let item2 = match reply.into() {
|
|
|
|
ReplyItem::Error(err) => return Err(err),
|
|
|
|
ReplyItem::Message(msg) => msg,
|
|
|
|
ReplyItem::Future(fut) => {
|
|
|
|
self.item = Some(item);
|
|
|
|
self.fut2 = Some(fut);
|
|
|
|
return self.poll();
|
|
|
|
}
|
2018-05-02 02:30:06 +02:00
|
|
|
ReplyItem::None => panic!("use after resolve"),
|
2018-05-02 02:19:15 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
let hnd: &mut F = unsafe { &mut *self.hnd.get() };
|
|
|
|
match (*hnd)(item, item2).respond_to(self.req.drop_state()) {
|
|
|
|
Ok(item) => match item.into().into() {
|
|
|
|
ReplyItem::Error(err) => return Err(err),
|
|
|
|
ReplyItem::Message(resp) => return Ok(Async::Ready(resp)),
|
|
|
|
ReplyItem::Future(fut) => {
|
|
|
|
self.fut3 = Some(fut);
|
|
|
|
return self.poll();
|
|
|
|
}
|
2018-05-02 02:30:06 +02:00
|
|
|
ReplyItem::None => panic!("use after resolve"),
|
2018-05-02 02:19:15 +02:00
|
|
|
},
|
|
|
|
Err(e) => return Err(e.into()),
|
|
|
|
}
|
2018-04-14 01:02:01 +02:00
|
|
|
}
|
2018-03-28 23:24:32 +02:00
|
|
|
Async::NotReady => return Ok(Async::NotReady),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let item = match self.fut2.as_mut().unwrap().poll()? {
|
|
|
|
Async::Ready(item) => item,
|
|
|
|
Async::NotReady => return Ok(Async::NotReady),
|
|
|
|
};
|
|
|
|
|
2018-04-14 01:02:01 +02:00
|
|
|
let hnd: &mut F = unsafe { &mut *self.hnd.get() };
|
2018-03-28 23:24:32 +02:00
|
|
|
let item = match (*hnd)(self.item.take().unwrap(), item)
|
2018-04-11 21:27:17 +02:00
|
|
|
.respond_to(self.req.drop_state())
|
2018-03-28 23:24:32 +02:00
|
|
|
{
|
|
|
|
Ok(item) => item.into(),
|
|
|
|
Err(err) => return Err(err.into()),
|
|
|
|
};
|
|
|
|
|
|
|
|
match item.into() {
|
2018-05-02 02:19:15 +02:00
|
|
|
ReplyItem::Error(err) => return Err(err),
|
2018-03-28 23:24:32 +02:00
|
|
|
ReplyItem::Message(resp) => return Ok(Async::Ready(resp)),
|
|
|
|
ReplyItem::Future(fut) => self.fut3 = Some(fut),
|
2018-05-02 02:30:06 +02:00
|
|
|
ReplyItem::None => panic!("use after resolve"),
|
2018-03-28 23:24:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
self.poll()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-04 07:06:18 +02:00
|
|
|
pub struct With3<T1, T2, T3, S, F, R>
|
2018-04-14 01:02:01 +02:00
|
|
|
where
|
|
|
|
F: Fn(T1, T2, T3) -> R,
|
|
|
|
T1: FromRequest<S> + 'static,
|
|
|
|
T2: FromRequest<S> + 'static,
|
|
|
|
T3: FromRequest<S> + 'static,
|
|
|
|
S: 'static,
|
2018-04-04 07:06:18 +02:00
|
|
|
{
|
2018-03-28 23:24:32 +02:00
|
|
|
hnd: Rc<UnsafeCell<F>>,
|
2018-04-04 07:06:18 +02:00
|
|
|
cfg1: ExtractorConfig<S, T1>,
|
|
|
|
cfg2: ExtractorConfig<S, T2>,
|
|
|
|
cfg3: ExtractorConfig<S, T3>,
|
2018-03-28 23:24:32 +02:00
|
|
|
_s: PhantomData<S>,
|
|
|
|
}
|
|
|
|
|
2018-03-31 18:58:33 +02:00
|
|
|
impl<T1, T2, T3, S, F, R> With3<T1, T2, T3, S, F, R>
|
2018-04-14 01:02:01 +02:00
|
|
|
where
|
|
|
|
F: Fn(T1, T2, T3) -> R,
|
|
|
|
T1: FromRequest<S> + 'static,
|
|
|
|
T2: FromRequest<S> + 'static,
|
|
|
|
T3: FromRequest<S> + 'static,
|
|
|
|
S: 'static,
|
2018-03-31 18:58:33 +02:00
|
|
|
{
|
2018-04-14 01:02:01 +02:00
|
|
|
pub fn new(
|
|
|
|
f: F, cfg1: ExtractorConfig<S, T1>, cfg2: ExtractorConfig<S, T2>,
|
|
|
|
cfg3: ExtractorConfig<S, T3>,
|
|
|
|
) -> Self {
|
|
|
|
With3 {
|
|
|
|
hnd: Rc::new(UnsafeCell::new(f)),
|
|
|
|
cfg1,
|
|
|
|
cfg2,
|
|
|
|
cfg3,
|
|
|
|
_s: PhantomData,
|
|
|
|
}
|
2018-03-31 18:58:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-28 23:24:32 +02:00
|
|
|
impl<T1, T2, T3, S, F, R> Handler<S> for With3<T1, T2, T3, S, F, R>
|
2018-04-14 01:02:01 +02:00
|
|
|
where
|
|
|
|
F: Fn(T1, T2, T3) -> R + 'static,
|
|
|
|
R: Responder + 'static,
|
|
|
|
T1: FromRequest<S>,
|
|
|
|
T2: FromRequest<S>,
|
|
|
|
T3: FromRequest<S>,
|
|
|
|
T1: 'static,
|
|
|
|
T2: 'static,
|
|
|
|
T3: 'static,
|
|
|
|
S: 'static,
|
2018-03-28 23:24:32 +02:00
|
|
|
{
|
2018-05-02 02:19:15 +02:00
|
|
|
type Result = Reply<HttpResponse>;
|
2018-03-28 23:24:32 +02:00
|
|
|
|
|
|
|
fn handle(&mut self, req: HttpRequest<S>) -> Self::Result {
|
2018-04-14 01:02:01 +02:00
|
|
|
let mut fut = WithHandlerFut3 {
|
2018-03-29 18:26:01 +02:00
|
|
|
req,
|
|
|
|
hnd: Rc::clone(&self.hnd),
|
2018-04-04 07:06:18 +02:00
|
|
|
cfg1: self.cfg1.clone(),
|
|
|
|
cfg2: self.cfg2.clone(),
|
|
|
|
cfg3: self.cfg3.clone(),
|
2018-03-29 18:26:01 +02:00
|
|
|
started: false,
|
|
|
|
item1: None,
|
|
|
|
item2: None,
|
|
|
|
fut1: None,
|
|
|
|
fut2: None,
|
|
|
|
fut3: None,
|
|
|
|
fut4: None,
|
|
|
|
};
|
|
|
|
match fut.poll() {
|
|
|
|
Ok(Async::Ready(resp)) => Reply::response(resp),
|
|
|
|
Ok(Async::NotReady) => Reply::async(fut),
|
|
|
|
Err(e) => Reply::response(e),
|
|
|
|
}
|
2018-03-28 23:24:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct WithHandlerFut3<T1, T2, T3, S, F, R>
|
2018-04-14 01:02:01 +02:00
|
|
|
where
|
|
|
|
F: Fn(T1, T2, T3) -> R + 'static,
|
|
|
|
R: Responder + 'static,
|
|
|
|
T1: FromRequest<S> + 'static,
|
|
|
|
T2: FromRequest<S> + 'static,
|
|
|
|
T3: FromRequest<S> + 'static,
|
|
|
|
S: 'static,
|
2018-03-28 23:24:32 +02:00
|
|
|
{
|
|
|
|
hnd: Rc<UnsafeCell<F>>,
|
|
|
|
req: HttpRequest<S>,
|
2018-04-04 07:06:18 +02:00
|
|
|
cfg1: ExtractorConfig<S, T1>,
|
|
|
|
cfg2: ExtractorConfig<S, T2>,
|
|
|
|
cfg3: ExtractorConfig<S, T3>,
|
2018-03-29 18:26:01 +02:00
|
|
|
started: bool,
|
2018-03-28 23:24:32 +02:00
|
|
|
item1: Option<T1>,
|
|
|
|
item2: Option<T2>,
|
2018-04-14 01:02:01 +02:00
|
|
|
fut1: Option<Box<Future<Item = T1, Error = Error>>>,
|
|
|
|
fut2: Option<Box<Future<Item = T2, Error = Error>>>,
|
|
|
|
fut3: Option<Box<Future<Item = T3, Error = Error>>>,
|
|
|
|
fut4: Option<Box<Future<Item = HttpResponse, Error = Error>>>,
|
2018-03-28 23:24:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T1, T2, T3, S, F, R> Future for WithHandlerFut3<T1, T2, T3, S, F, R>
|
2018-04-14 01:02:01 +02:00
|
|
|
where
|
|
|
|
F: Fn(T1, T2, T3) -> R + 'static,
|
|
|
|
R: Responder + 'static,
|
|
|
|
T1: FromRequest<S> + 'static,
|
|
|
|
T2: FromRequest<S> + 'static,
|
|
|
|
T3: FromRequest<S> + 'static,
|
|
|
|
S: 'static,
|
2018-03-28 23:24:32 +02:00
|
|
|
{
|
|
|
|
type Item = HttpResponse;
|
|
|
|
type Error = Error;
|
|
|
|
|
|
|
|
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
|
|
|
if let Some(ref mut fut) = self.fut4 {
|
2018-04-14 01:02:01 +02:00
|
|
|
return fut.poll();
|
2018-03-28 23:24:32 +02:00
|
|
|
}
|
|
|
|
|
2018-03-29 18:26:01 +02:00
|
|
|
if !self.started {
|
|
|
|
self.started = true;
|
2018-05-02 15:07:30 +02:00
|
|
|
let reply = T1::from_request(&self.req, self.cfg1.as_ref()).into();
|
2018-05-02 02:19:15 +02:00
|
|
|
let item1 = match reply.into() {
|
|
|
|
ReplyItem::Error(err) => return Err(err),
|
|
|
|
ReplyItem::Message(msg) => msg,
|
|
|
|
ReplyItem::Future(fut) => {
|
|
|
|
self.fut1 = Some(fut);
|
|
|
|
return self.poll();
|
|
|
|
}
|
2018-05-02 02:30:06 +02:00
|
|
|
ReplyItem::None => panic!("use after resolve"),
|
2018-05-02 02:19:15 +02:00
|
|
|
};
|
|
|
|
|
2018-05-02 15:07:30 +02:00
|
|
|
let reply = T2::from_request(&self.req, self.cfg2.as_ref()).into();
|
2018-05-02 02:19:15 +02:00
|
|
|
let item2 = match reply.into() {
|
|
|
|
ReplyItem::Error(err) => return Err(err),
|
|
|
|
ReplyItem::Message(msg) => msg,
|
|
|
|
ReplyItem::Future(fut) => {
|
|
|
|
self.item1 = Some(item1);
|
|
|
|
self.fut2 = Some(fut);
|
|
|
|
return self.poll();
|
2018-04-14 01:02:01 +02:00
|
|
|
}
|
2018-05-02 02:30:06 +02:00
|
|
|
ReplyItem::None => panic!("use after resolve"),
|
2018-05-02 02:19:15 +02:00
|
|
|
};
|
|
|
|
|
2018-05-02 15:07:30 +02:00
|
|
|
let reply = T3::from_request(&self.req, self.cfg3.as_ref()).into();
|
2018-05-02 02:19:15 +02:00
|
|
|
let item3 = match reply.into() {
|
|
|
|
ReplyItem::Error(err) => return Err(err),
|
|
|
|
ReplyItem::Message(msg) => msg,
|
|
|
|
ReplyItem::Future(fut) => {
|
|
|
|
self.item1 = Some(item1);
|
|
|
|
self.item2 = Some(item2);
|
|
|
|
self.fut3 = Some(fut);
|
|
|
|
return self.poll();
|
2018-03-29 18:26:01 +02:00
|
|
|
}
|
2018-05-02 02:30:06 +02:00
|
|
|
ReplyItem::None => panic!("use after resolve"),
|
2018-05-02 02:19:15 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
let hnd: &mut F = unsafe { &mut *self.hnd.get() };
|
|
|
|
match (*hnd)(item1, item2, item3).respond_to(self.req.drop_state()) {
|
|
|
|
Ok(item) => match item.into().into() {
|
|
|
|
ReplyItem::Error(err) => return Err(err),
|
|
|
|
ReplyItem::Message(resp) => return Ok(Async::Ready(resp)),
|
|
|
|
ReplyItem::Future(fut) => {
|
|
|
|
self.fut4 = Some(fut);
|
|
|
|
return self.poll();
|
|
|
|
}
|
2018-05-02 02:30:06 +02:00
|
|
|
ReplyItem::None => panic!("use after resolve"),
|
2018-05-02 02:19:15 +02:00
|
|
|
},
|
|
|
|
Err(e) => return Err(e.into()),
|
2018-03-29 18:26:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-28 23:24:32 +02:00
|
|
|
if self.fut1.is_some() {
|
|
|
|
match self.fut1.as_mut().unwrap().poll()? {
|
|
|
|
Async::Ready(item) => {
|
|
|
|
self.item1 = Some(item);
|
|
|
|
self.fut1.take();
|
2018-05-02 15:07:30 +02:00
|
|
|
let reply = T2::from_request(&self.req, self.cfg2.as_ref()).into();
|
2018-05-02 02:19:15 +02:00
|
|
|
let item2 = match reply.into() {
|
|
|
|
ReplyItem::Error(err) => return Err(err),
|
|
|
|
ReplyItem::Message(msg) => msg,
|
|
|
|
ReplyItem::Future(fut) => {
|
|
|
|
self.fut2 = Some(fut);
|
|
|
|
return self.poll();
|
|
|
|
}
|
2018-05-02 02:30:06 +02:00
|
|
|
ReplyItem::None => panic!("use after resolve"),
|
2018-05-02 02:19:15 +02:00
|
|
|
};
|
|
|
|
|
2018-05-02 15:07:30 +02:00
|
|
|
let reply = T3::from_request(&self.req, self.cfg3.as_ref()).into();
|
2018-05-02 02:19:15 +02:00
|
|
|
let item3 = match reply.into() {
|
|
|
|
ReplyItem::Error(err) => return Err(err),
|
|
|
|
ReplyItem::Message(msg) => msg,
|
|
|
|
ReplyItem::Future(fut) => {
|
|
|
|
self.item2 = Some(item2);
|
|
|
|
self.fut3 = Some(fut);
|
|
|
|
return self.poll();
|
|
|
|
}
|
2018-05-02 02:30:06 +02:00
|
|
|
ReplyItem::None => panic!("use after resolve"),
|
2018-05-02 02:19:15 +02:00
|
|
|
};
|
|
|
|
let hnd: &mut F = unsafe { &mut *self.hnd.get() };
|
|
|
|
match (*hnd)(self.item1.take().unwrap(), item2, item3)
|
|
|
|
.respond_to(self.req.drop_state())
|
|
|
|
{
|
|
|
|
Ok(item) => match item.into().into() {
|
|
|
|
ReplyItem::Error(err) => return Err(err),
|
|
|
|
ReplyItem::Message(resp) => return Ok(Async::Ready(resp)),
|
|
|
|
ReplyItem::Future(fut) => {
|
|
|
|
self.fut4 = Some(fut);
|
|
|
|
return self.poll();
|
|
|
|
}
|
2018-05-02 02:30:06 +02:00
|
|
|
ReplyItem::None => panic!("use after resolve"),
|
2018-05-02 02:19:15 +02:00
|
|
|
},
|
|
|
|
Err(e) => return Err(e.into()),
|
|
|
|
}
|
2018-04-14 01:02:01 +02:00
|
|
|
}
|
2018-03-28 23:24:32 +02:00
|
|
|
Async::NotReady => return Ok(Async::NotReady),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.fut2.is_some() {
|
|
|
|
match self.fut2.as_mut().unwrap().poll()? {
|
|
|
|
Async::Ready(item) => {
|
|
|
|
self.fut2.take();
|
2018-05-02 15:07:30 +02:00
|
|
|
let reply = T3::from_request(&self.req, self.cfg3.as_ref()).into();
|
2018-05-02 02:19:15 +02:00
|
|
|
let item3 = match reply.into() {
|
|
|
|
ReplyItem::Error(err) => return Err(err),
|
|
|
|
ReplyItem::Message(msg) => msg,
|
|
|
|
ReplyItem::Future(fut) => {
|
|
|
|
self.item2 = Some(item);
|
|
|
|
self.fut3 = Some(fut);
|
|
|
|
return self.poll();
|
|
|
|
}
|
2018-05-02 02:30:06 +02:00
|
|
|
ReplyItem::None => panic!("use after resolve"),
|
2018-05-02 02:19:15 +02:00
|
|
|
};
|
|
|
|
let hnd: &mut F = unsafe { &mut *self.hnd.get() };
|
|
|
|
match (*hnd)(self.item1.take().unwrap(), item, item3)
|
|
|
|
.respond_to(self.req.drop_state())
|
|
|
|
{
|
|
|
|
Ok(item) => match item.into().into() {
|
|
|
|
ReplyItem::Error(err) => return Err(err),
|
|
|
|
ReplyItem::Message(resp) => return Ok(Async::Ready(resp)),
|
|
|
|
ReplyItem::Future(fut) => {
|
|
|
|
self.fut4 = Some(fut);
|
|
|
|
return self.poll();
|
|
|
|
}
|
2018-05-02 02:30:06 +02:00
|
|
|
ReplyItem::None => panic!("use after resolve"),
|
2018-05-02 02:19:15 +02:00
|
|
|
},
|
|
|
|
Err(e) => return Err(e.into()),
|
|
|
|
}
|
2018-04-14 01:02:01 +02:00
|
|
|
}
|
2018-03-28 23:24:32 +02:00
|
|
|
Async::NotReady => return Ok(Async::NotReady),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let item = match self.fut3.as_mut().unwrap().poll()? {
|
|
|
|
Async::Ready(item) => item,
|
|
|
|
Async::NotReady => return Ok(Async::NotReady),
|
|
|
|
};
|
|
|
|
|
2018-04-14 01:02:01 +02:00
|
|
|
let hnd: &mut F = unsafe { &mut *self.hnd.get() };
|
2018-04-29 18:09:08 +02:00
|
|
|
let item = match (*hnd)(
|
|
|
|
self.item1.take().unwrap(),
|
|
|
|
self.item2.take().unwrap(),
|
|
|
|
item,
|
|
|
|
).respond_to(self.req.drop_state())
|
|
|
|
{
|
|
|
|
Ok(item) => item.into(),
|
|
|
|
Err(err) => return Err(err.into()),
|
|
|
|
};
|
2018-03-28 23:24:32 +02:00
|
|
|
|
|
|
|
match item.into() {
|
2018-05-02 02:19:15 +02:00
|
|
|
ReplyItem::Error(err) => return Ok(Async::Ready(err.into())),
|
2018-03-28 23:24:32 +02:00
|
|
|
ReplyItem::Message(resp) => return Ok(Async::Ready(resp)),
|
|
|
|
ReplyItem::Future(fut) => self.fut4 = Some(fut),
|
2018-05-02 02:30:06 +02:00
|
|
|
ReplyItem::None => panic!("use after resolve"),
|
2018-03-28 23:24:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
self.poll()
|
|
|
|
}
|
|
|
|
}
|