use std::error::Error as StdError;
use std::fmt;
use std::marker::PhantomData;
use futures::{future, Future, IntoFuture};
use body::Payload;
use common::Never;
use ::{Request, Response};
pub trait Service {
type ReqBody: Payload;
type ResBody: Payload;
type Error: Into<Box<StdError + Send + Sync>>;
type Future: Future<Item=Response<Self::ResBody>, Error=Self::Error>;
fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future;
}
pub fn service_fn<F, R, S>(f: F) -> ServiceFn<F, R>
where
F: Fn(Request<R>) -> S,
S: IntoFuture,
{
ServiceFn {
f,
_req: PhantomData,
}
}
pub fn service_fn_ok<F, R, S>(f: F) -> ServiceFnOk<F, R>
where
F: Fn(Request<R>) -> Response<S>,
S: Payload,
{
ServiceFnOk {
f,
_req: PhantomData,
}
}
pub struct ServiceFn<F, R> {
f: F,
_req: PhantomData<fn(R)>,
}
impl<F, ReqBody, Ret, ResBody> Service for ServiceFn<F, ReqBody>
where
F: Fn(Request<ReqBody>) -> Ret,
ReqBody: Payload,
Ret: IntoFuture<Item=Response<ResBody>>,
Ret::Error: Into<Box<StdError + Send + Sync>>,
ResBody: Payload,
{
type ReqBody = ReqBody;
type ResBody = ResBody;
type Error = Ret::Error;
type Future = Ret::Future;
fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future {
(self.f)(req).into_future()
}
}
impl<F, R> IntoFuture for ServiceFn<F, R> {
type Future = future::FutureResult<Self::Item, Self::Error>;
type Item = Self;
type Error = Never;
fn into_future(self) -> Self::Future {
future::ok(self)
}
}
impl<F, R> fmt::Debug for ServiceFn<F, R> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("impl Service")
.finish()
}
}
pub struct ServiceFnOk<F, R> {
f: F,
_req: PhantomData<fn(R)>,
}
impl<F, ReqBody, ResBody> Service for ServiceFnOk<F, ReqBody>
where
F: Fn(Request<ReqBody>) -> Response<ResBody>,
ReqBody: Payload,
ResBody: Payload,
{
type ReqBody = ReqBody;
type ResBody = ResBody;
type Error = Never;
type Future = future::FutureResult<Response<ResBody>, Never>;
fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future {
future::ok((self.f)(req))
}
}
impl<F, R> IntoFuture for ServiceFnOk<F, R> {
type Future = future::FutureResult<Self::Item, Self::Error>;
type Item = Self;
type Error = Never;
fn into_future(self) -> Self::Future {
future::ok(self)
}
}
impl<F, R> fmt::Debug for ServiceFnOk<F, R> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("impl Service")
.finish()
}
}