use futures::{Async, Future, Poll}; use std::cell::UnsafeCell; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use std::rc::Rc; use error::Error; use handler::{FromRequest, Handler, Reply, ReplyItem, Responder}; use httprequest::HttpRequest; use httpresponse::HttpResponse; pub struct ExtractorConfig> { cfg: Rc>, } impl> Default for ExtractorConfig { fn default() -> Self { ExtractorConfig { cfg: Rc::new(UnsafeCell::new(T::Config::default())), } } } impl> Clone for ExtractorConfig { fn clone(&self) -> Self { ExtractorConfig { cfg: Rc::clone(&self.cfg), } } } impl> AsRef for ExtractorConfig { fn as_ref(&self) -> &T::Config { unsafe { &*self.cfg.get() } } } impl> Deref for ExtractorConfig { type Target = T::Config; fn deref(&self) -> &T::Config { unsafe { &*self.cfg.get() } } } impl> DerefMut for ExtractorConfig { fn deref_mut(&mut self) -> &mut T::Config { unsafe { &mut *self.cfg.get() } } } pub struct With where F: Fn(T) -> R, T: FromRequest, S: 'static, { hnd: Rc>, cfg: ExtractorConfig, _s: PhantomData, } impl With where F: Fn(T) -> R, T: FromRequest, S: 'static, { pub fn new(f: F, cfg: ExtractorConfig) -> Self { With { cfg, hnd: Rc::new(UnsafeCell::new(f)), _s: PhantomData, } } } impl Handler for With where F: Fn(T) -> R + 'static, R: Responder + 'static, T: FromRequest + 'static, S: 'static, { type Result = Reply; fn handle(&mut self, req: HttpRequest) -> Self::Result { let mut fut = WithHandlerFut { req, started: false, hnd: Rc::clone(&self.hnd), cfg: self.cfg.clone(), fut1: None, fut2: None, }; match fut.poll() { Ok(Async::Ready(resp)) => Reply::response(resp), Ok(Async::NotReady) => Reply::async(fut), Err(e) => Reply::response(e), } } } struct WithHandlerFut where F: Fn(T) -> R, R: Responder, T: FromRequest + 'static, S: 'static, { started: bool, hnd: Rc>, cfg: ExtractorConfig, req: HttpRequest, fut1: Option>>, fut2: Option>>, } impl Future for WithHandlerFut where F: Fn(T) -> R, R: Responder + 'static, T: FromRequest + 'static, S: 'static, { type Item = HttpResponse; type Error = Error; fn poll(&mut self) -> Poll { if let Some(ref mut fut) = self.fut2 { return fut.poll(); } let item = if !self.started { self.started = true; let mut fut = T::from_request(&self.req, self.cfg.as_ref()); match fut.poll() { Ok(Async::Ready(item)) => item, Ok(Async::NotReady) => { self.fut1 = Some(Box::new(fut)); return Ok(Async::NotReady); } Err(e) => return Err(e), } } else { match self.fut1.as_mut().unwrap().poll()? { Async::Ready(item) => item, Async::NotReady => return Ok(Async::NotReady), } }; let hnd: &mut F = unsafe { &mut *self.hnd.get() }; let item = match (*hnd)(item).respond_to(self.req.drop_state()) { Ok(item) => item.into(), Err(e) => return Err(e.into()), }; match item.into() { ReplyItem::Message(resp) => Ok(Async::Ready(resp)), ReplyItem::Future(fut) => { self.fut2 = Some(fut); self.poll() } } } } pub struct With2 where F: Fn(T1, T2) -> R, T1: FromRequest + 'static, T2: FromRequest + 'static, S: 'static, { hnd: Rc>, cfg1: ExtractorConfig, cfg2: ExtractorConfig, _s: PhantomData, } impl With2 where F: Fn(T1, T2) -> R, T1: FromRequest + 'static, T2: FromRequest + 'static, S: 'static, { pub fn new( f: F, cfg1: ExtractorConfig, cfg2: ExtractorConfig, ) -> Self { With2 { hnd: Rc::new(UnsafeCell::new(f)), cfg1, cfg2, _s: PhantomData, } } } impl Handler for With2 where F: Fn(T1, T2) -> R + 'static, R: Responder + 'static, T1: FromRequest + 'static, T2: FromRequest + 'static, S: 'static, { type Result = Reply; fn handle(&mut self, req: HttpRequest) -> Self::Result { let mut fut = WithHandlerFut2 { req, started: false, hnd: Rc::clone(&self.hnd), cfg1: self.cfg1.clone(), cfg2: self.cfg2.clone(), item: None, fut1: None, fut2: None, fut3: None, }; match fut.poll() { Ok(Async::Ready(resp)) => Reply::response(resp), Ok(Async::NotReady) => Reply::async(fut), Err(e) => Reply::response(e), } } } struct WithHandlerFut2 where F: Fn(T1, T2) -> R + 'static, R: Responder + 'static, T1: FromRequest + 'static, T2: FromRequest + 'static, S: 'static, { started: bool, hnd: Rc>, cfg1: ExtractorConfig, cfg2: ExtractorConfig, req: HttpRequest, item: Option, fut1: Option>>, fut2: Option>>, fut3: Option>>, } impl Future for WithHandlerFut2 where F: Fn(T1, T2) -> R + 'static, R: Responder + 'static, T1: FromRequest + 'static, T2: FromRequest + 'static, S: 'static, { type Item = HttpResponse; type Error = Error; fn poll(&mut self) -> Poll { if let Some(ref mut fut) = self.fut3 { return fut.poll(); } if !self.started { self.started = true; let mut fut = T1::from_request(&self.req, self.cfg1.as_ref()); match fut.poll() { Ok(Async::Ready(item1)) => { let mut fut = T2::from_request(&self.req, self.cfg2.as_ref()); match fut.poll() { Ok(Async::Ready(item2)) => { 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::Message(resp) => { return Ok(Async::Ready(resp)) } ReplyItem::Future(fut) => { self.fut3 = Some(fut); return self.poll(); } }, Err(e) => return Err(e.into()), } } Ok(Async::NotReady) => { self.item = Some(item1); self.fut2 = Some(Box::new(fut)); return Ok(Async::NotReady); } Err(e) => return Err(e), } } Ok(Async::NotReady) => { self.fut1 = Some(Box::new(fut)); return Ok(Async::NotReady); } Err(e) => return Err(e), } } if self.fut1.is_some() { match self.fut1.as_mut().unwrap().poll()? { Async::Ready(item) => { self.item = Some(item); self.fut1.take(); self.fut2 = Some(Box::new(T2::from_request( &self.req, self.cfg2.as_ref(), ))); } 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), }; let hnd: &mut F = unsafe { &mut *self.hnd.get() }; let item = match (*hnd)(self.item.take().unwrap(), item) .respond_to(self.req.drop_state()) { Ok(item) => item.into(), Err(err) => return Err(err.into()), }; match item.into() { ReplyItem::Message(resp) => return Ok(Async::Ready(resp)), ReplyItem::Future(fut) => self.fut3 = Some(fut), } self.poll() } } pub struct With3 where F: Fn(T1, T2, T3) -> R, T1: FromRequest + 'static, T2: FromRequest + 'static, T3: FromRequest + 'static, S: 'static, { hnd: Rc>, cfg1: ExtractorConfig, cfg2: ExtractorConfig, cfg3: ExtractorConfig, _s: PhantomData, } impl With3 where F: Fn(T1, T2, T3) -> R, T1: FromRequest + 'static, T2: FromRequest + 'static, T3: FromRequest + 'static, S: 'static, { pub fn new( f: F, cfg1: ExtractorConfig, cfg2: ExtractorConfig, cfg3: ExtractorConfig, ) -> Self { With3 { hnd: Rc::new(UnsafeCell::new(f)), cfg1, cfg2, cfg3, _s: PhantomData, } } } impl Handler for With3 where F: Fn(T1, T2, T3) -> R + 'static, R: Responder + 'static, T1: FromRequest, T2: FromRequest, T3: FromRequest, T1: 'static, T2: 'static, T3: 'static, S: 'static, { type Result = Reply; fn handle(&mut self, req: HttpRequest) -> Self::Result { let mut fut = WithHandlerFut3 { req, hnd: Rc::clone(&self.hnd), cfg1: self.cfg1.clone(), cfg2: self.cfg2.clone(), cfg3: self.cfg3.clone(), 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), } } } struct WithHandlerFut3 where F: Fn(T1, T2, T3) -> R + 'static, R: Responder + 'static, T1: FromRequest + 'static, T2: FromRequest + 'static, T3: FromRequest + 'static, S: 'static, { hnd: Rc>, req: HttpRequest, cfg1: ExtractorConfig, cfg2: ExtractorConfig, cfg3: ExtractorConfig, started: bool, item1: Option, item2: Option, fut1: Option>>, fut2: Option>>, fut3: Option>>, fut4: Option>>, } impl Future for WithHandlerFut3 where F: Fn(T1, T2, T3) -> R + 'static, R: Responder + 'static, T1: FromRequest + 'static, T2: FromRequest + 'static, T3: FromRequest + 'static, S: 'static, { type Item = HttpResponse; type Error = Error; fn poll(&mut self) -> Poll { if let Some(ref mut fut) = self.fut4 { return fut.poll(); } if !self.started { self.started = true; let mut fut = T1::from_request(&self.req, self.cfg1.as_ref()); match fut.poll() { Ok(Async::Ready(item1)) => { let mut fut = T2::from_request(&self.req, self.cfg2.as_ref()); match fut.poll() { Ok(Async::Ready(item2)) => { let mut fut = T3::from_request(&self.req, self.cfg3.as_ref()); match fut.poll() { Ok(Async::Ready(item3)) => { 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::Message(resp) => { return Ok(Async::Ready(resp)) } ReplyItem::Future(fut) => { self.fut4 = Some(fut); return self.poll(); } }, Err(e) => return Err(e.into()), } } Ok(Async::NotReady) => { self.item1 = Some(item1); self.item2 = Some(item2); self.fut3 = Some(Box::new(fut)); return Ok(Async::NotReady); } Err(e) => return Err(e), } } Ok(Async::NotReady) => { self.item1 = Some(item1); self.fut2 = Some(Box::new(fut)); return Ok(Async::NotReady); } Err(e) => return Err(e), } } Ok(Async::NotReady) => { self.fut1 = Some(Box::new(fut)); return Ok(Async::NotReady); } Err(e) => return Err(e), } } if self.fut1.is_some() { match self.fut1.as_mut().unwrap().poll()? { Async::Ready(item) => { self.item1 = Some(item); self.fut1.take(); self.fut2 = Some(Box::new(T2::from_request( &self.req, self.cfg2.as_ref(), ))); } Async::NotReady => return Ok(Async::NotReady), } } if self.fut2.is_some() { match self.fut2.as_mut().unwrap().poll()? { Async::Ready(item) => { self.item2 = Some(item); self.fut2.take(); self.fut3 = Some(Box::new(T3::from_request( &self.req, self.cfg3.as_ref(), ))); } 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), }; let hnd: &mut F = unsafe { &mut *self.hnd.get() }; 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()), }; match item.into() { ReplyItem::Message(resp) => return Ok(Async::Ready(resp)), ReplyItem::Future(fut) => self.fut4 = Some(fut), } self.poll() } }