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 data factory pub(crate) trait DataFactory { fn construct(&self) -> Box; } pub(crate) trait DataFactoryResult { fn poll_result(&mut self, extensions: &mut Extensions) -> Poll<(), ()>; } /// Application state pub struct Data(Arc); impl Data { pub(crate) fn new(state: T) -> Data { Data(Arc::new(state)) } /// Get referecnce to inner state type. pub fn get_ref(&self) -> &T { self.0.as_ref() } } impl Deref for Data { type Target = T; fn deref(&self) -> &T { self.0.as_ref() } } impl Clone for Data { fn clone(&self) -> Data { Data(self.0.clone()) } } impl FromRequest

for Data { 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 DataFactory for Data { fn construct(&self) -> Box { Box::new(DataFut { st: self.clone() }) } } struct DataFut { st: Data, } impl DataFactoryResult for DataFut { fn poll_result(&mut self, extensions: &mut Extensions) -> Poll<(), ()> { extensions.insert(self.st.clone()); Ok(Async::Ready(())) } } impl DataFactory for F where F: Fn() -> Out + 'static, Out: IntoFuture + 'static, Out::Error: std::fmt::Debug, { fn construct(&self) -> Box { Box::new(DataFactoryFut { fut: (*self)().into_future(), }) } } struct DataFactoryFut where F: Future, F::Error: std::fmt::Debug, { fut: F, } impl DataFactoryResult for DataFactoryFut 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(Data::new(s)); Ok(Async::Ready(())) } Ok(Async::NotReady) => Ok(Async::NotReady), Err(e) => { log::error!("Can not construct application state: {:?}", e); Err(()) } } } }