use std::ops::Deref; use std::rc::Rc; use actix_http::error::{Error, ErrorInternalServerError}; use actix_http::Extensions; use futures::future::{err, ok, FutureResult}; use futures::{Async, Future, IntoFuture, Poll}; use crate::handler::FromRequest; use crate::service::ServiceRequest; /// Application state factory pub(crate) trait StateFactory { fn construct(&self) -> Box; } pub(crate) trait StateFactoryResult { fn poll_result(&mut self, extensions: &mut Extensions) -> Poll<(), ()>; } /// Application state pub struct State(Rc); impl State { pub fn new(state: S) -> State { State(Rc::new(state)) } pub fn get_ref(&self) -> &S { self.0.as_ref() } } impl Deref for State { type Target = S; fn deref(&self) -> &S { self.0.as_ref() } } impl Clone for State { fn clone(&self) -> State { State(self.0.clone()) } } impl FromRequest

for State { type Error = Error; type Future = FutureResult; #[inline] fn from_request(req: &mut ServiceRequest

) -> Self::Future { if let Some(st) = req.app_extensions().get::>() { ok(st.clone()) } else { err(ErrorInternalServerError( "State is not configured, use App::state()", )) } } } impl StateFactory for State { fn construct(&self) -> Box { Box::new(StateFut { st: self.clone() }) } } struct StateFut { st: State, } impl StateFactoryResult for StateFut { fn poll_result(&mut self, extensions: &mut Extensions) -> Poll<(), ()> { extensions.insert(self.st.clone()); Ok(Async::Ready(())) } } impl StateFactory for F where F: Fn() -> Out + 'static, Out: IntoFuture + 'static, Out::Error: std::fmt::Debug, { fn construct(&self) -> Box { Box::new(StateFactoryFut { fut: (*self)().into_future(), }) } } struct StateFactoryFut where F: Future, F::Error: std::fmt::Debug, { fut: F, } impl StateFactoryResult for StateFactoryFut where F: Future, F::Error: std::fmt::Debug, { fn poll_result(&mut self, extensions: &mut Extensions) -> Poll<(), ()> { match self.fut.poll() { Ok(Async::Ready(s)) => { extensions.insert(State::new(s)); Ok(Async::Ready(())) } Ok(Async::NotReady) => Ok(Async::NotReady), Err(e) => { log::error!("Can not construct application state: {:?}", e); Err(()) } } } }