use std::ops::Deref; use std::sync::Arc; use actix_http::error::{Error, ErrorInternalServerError}; use actix_http::Extensions; use futures::{Async, Future, IntoFuture, Poll}; use crate::extract::FromRequest; use crate::service::ServiceFromRequest; /// 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(Arc); impl State { pub(crate) fn new(state: T) -> State { State(Arc::new(state)) } /// Get referecnce to inner state type. pub fn get_ref(&self) -> &T { self.0.as_ref() } } impl Deref for State { type Target = T; fn deref(&self) -> &T { 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 = Result; #[inline] fn from_request(req: &mut ServiceFromRequest

) -> Self::Future { if let Some(st) = req.config().extensions().get::>() { Ok(st.clone()) } else { Err(ErrorInternalServerError( "State is not configured, to configure 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(()) } } } }