use std::{fmt, future::Future, sync::Arc};
#[cfg(feature = "service_send")]
use futures::future::BoxFuture;
#[cfg(not(feature = "service_send"))]
use futures::future::LocalBoxFuture as BoxFuture;
mod ext;
mod service_fn;
#[cfg(feature = "tower")]
mod tower_adapter;
pub use ext::*;
pub use service_fn::{service_fn, ServiceFn};
#[cfg(feature = "tower")]
pub use tower_adapter::*;
pub trait Service<Cx, Request> {
type Response;
type Error;
#[cfg(feature = "service_send")]
fn call(
&self,
cx: &mut Cx,
req: Request,
) -> impl Future<Output = Result<Self::Response, Self::Error>> + Send;
#[cfg(not(feature = "service_send"))]
fn call(
&self,
cx: &mut Cx,
req: Request,
) -> impl Future<Output = Result<Self::Response, Self::Error>>;
}
macro_rules! impl_service_ref {
($t: tt) => {
impl<Cx, Req, T> Service<Cx, Req> for $t<T>
where
T: Service<Cx, Req>,
{
type Response = T::Response;
type Error = T::Error;
#[cfg(feature = "service_send")]
fn call(
&self,
cx: &mut Cx,
req: Req,
) -> impl Future<Output = Result<Self::Response, Self::Error>> + Send {
(&**self).call(cx, req)
}
#[cfg(not(feature = "service_send"))]
fn call(
&self,
cx: &mut Cx,
req: Req,
) -> impl Future<Output = Result<Self::Response, Self::Error>> {
(&**self).call(cx, req)
}
}
};
}
impl_service_ref!(Arc);
impl_service_ref!(Box);
macro_rules! impl_unary_service_ref {
($t: tt) => {
impl<Req, T> UnaryService<Req> for $t<T>
where
T: UnaryService<Req>,
{
type Response = T::Response;
type Error = T::Error;
#[cfg(feature = "service_send")]
fn call(
&self,
req: Req,
) -> impl Future<Output = Result<Self::Response, Self::Error>> + Send {
(&**self).call(req)
}
#[cfg(not(feature = "service_send"))]
fn call(&self, req: Req) -> impl Future<Output = Result<Self::Response, Self::Error>> {
(&**self).call(req)
}
}
};
}
pub trait UnaryService<Request> {
type Response;
type Error;
#[cfg(feature = "service_send")]
fn call(
&self,
req: Request,
) -> impl Future<Output = Result<Self::Response, Self::Error>> + Send;
#[cfg(not(feature = "service_send"))]
fn call(&self, req: Request) -> impl Future<Output = Result<Self::Response, Self::Error>>;
}
impl_unary_service_ref!(Arc);
impl_unary_service_ref!(Box);
pub struct BoxService<Cx, T, U, E> {
raw: *mut (),
vtable: ServiceVtable<Cx, T, U, E>,
}
impl<Cx, T, U, E> BoxService<Cx, T, U, E> {
#[cfg(feature = "service_send")]
pub fn new<S>(s: S) -> Self
where
S: Service<Cx, T, Response = U, Error = E> + Send + Sync + 'static,
T: 'static,
{
let raw = Box::into_raw(Box::new(s)) as *mut ();
BoxService {
raw,
vtable: ServiceVtable {
call: call::<Cx, T, S>,
drop: drop::<S>,
},
}
}
#[cfg(not(feature = "service_send"))]
pub fn new<S>(s: S) -> Self
where
S: Service<Cx, T, Response = U, Error = E> + 'static,
T: 'static,
{
let raw = Box::into_raw(Box::new(s)) as *mut ();
BoxService {
raw,
vtable: ServiceVtable {
call: call::<Cx, T, S>,
drop: drop::<S>,
},
}
}
}
impl<Cx, T, U, E> Drop for BoxService<Cx, T, U, E> {
fn drop(&mut self) {
unsafe { (self.vtable.drop)(self.raw) };
}
}
impl<Cx, T, U, E> fmt::Debug for BoxService<Cx, T, U, E> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("BoxService").finish()
}
}
impl<Cx, T, U, E> Service<Cx, T> for BoxService<Cx, T, U, E> {
type Response = U;
type Error = E;
#[cfg(feature = "service_send")]
fn call(
&self,
cx: &mut Cx,
req: T,
) -> impl Future<Output = Result<Self::Response, Self::Error>> + Send {
unsafe { (self.vtable.call)(self.raw, cx, req) }
}
#[cfg(not(feature = "service_send"))]
fn call(
&self,
cx: &mut Cx,
req: T,
) -> impl Future<Output = Result<Self::Response, Self::Error>> {
unsafe { (self.vtable.call)(self.raw, cx, req) }
}
}
#[cfg(feature = "service_send")]
unsafe impl<Cx, T, U, E> Send for BoxService<Cx, T, U, E> {}
#[cfg(feature = "service_send")]
unsafe impl<Cx, T, U, E> Sync for BoxService<Cx, T, U, E> {}
struct ServiceVtable<Cx, T, U, E> {
call: unsafe fn(raw: *mut (), cx: &mut Cx, req: T) -> BoxFuture<'_, Result<U, E>>,
drop: unsafe fn(raw: *mut ()),
}
#[cfg(feature = "service_send")]
pub struct BoxCloneService<Cx, T, U, E> {
raw: *mut (),
vtable: CloneServiceVtable<Cx, T, U, E>,
}
#[cfg(not(feature = "service_send"))]
pub struct BoxCloneService<Cx, T, U, E> {
raw: *mut (),
vtable: CloneServiceVtable<Cx, T, U, E>,
}
impl<Cx, T, U, E> BoxCloneService<Cx, T, U, E> {
#[cfg(feature = "service_send")]
pub fn new<S>(s: S) -> Self
where
S: Service<Cx, T, Response = U, Error = E> + Clone + Send + Sync + 'static,
T: 'static,
{
let raw = Box::into_raw(Box::new(s)) as *mut ();
BoxCloneService {
raw,
vtable: CloneServiceVtable {
call: call::<Cx, T, S>,
clone: clone::<Cx, T, S>,
drop: drop::<S>,
},
}
}
#[cfg(not(feature = "service_send"))]
pub fn new<S>(s: S) -> Self
where
S: Service<Cx, T, Response = U, Error = E> + Clone + 'static,
T: 'static,
{
let raw = Box::into_raw(Box::new(s)) as *mut ();
BoxCloneService {
raw,
vtable: CloneServiceVtable {
call: call::<Cx, T, S>,
clone: clone::<Cx, T, S>,
drop: drop::<S>,
},
}
}
}
impl<Cx, T, U, E> Drop for BoxCloneService<Cx, T, U, E> {
fn drop(&mut self) {
unsafe { (self.vtable.drop)(self.raw) };
}
}
impl<Cx, T, U, E> Clone for BoxCloneService<Cx, T, U, E> {
fn clone(&self) -> Self {
unsafe { (self.vtable.clone)(self.raw) }
}
}
impl<Cx, T, U, E> fmt::Debug for BoxCloneService<Cx, T, U, E> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("BoxCloneService").finish()
}
}
impl<Cx, T, U, E> Service<Cx, T> for BoxCloneService<Cx, T, U, E> {
type Response = U;
type Error = E;
#[cfg(feature = "service_send")]
fn call(
&self,
cx: &mut Cx,
req: T,
) -> impl Future<Output = Result<Self::Response, Self::Error>> + Send {
unsafe { (self.vtable.call)(self.raw, cx, req) }
}
#[cfg(not(feature = "service_send"))]
fn call(
&self,
cx: &mut Cx,
req: T,
) -> impl Future<Output = Result<Self::Response, Self::Error>> {
unsafe { (self.vtable.call)(self.raw, cx, req) }
}
}
#[cfg(feature = "service_send")]
unsafe impl<Cx, T, U, E> Send for BoxCloneService<Cx, T, U, E> {}
#[cfg(feature = "service_send")]
unsafe impl<Cx, T, U, E> Sync for BoxCloneService<Cx, T, U, E> {}
struct CloneServiceVtable<Cx, T, U, E> {
call: unsafe fn(raw: *mut (), cx: &mut Cx, req: T) -> BoxFuture<'_, Result<U, E>>,
clone: unsafe fn(raw: *mut ()) -> BoxCloneService<Cx, T, U, E>,
drop: unsafe fn(raw: *mut ()),
}
fn call<Cx, Req, S>(
raw: *mut (),
cx: &mut Cx,
req: Req,
) -> BoxFuture<'_, Result<S::Response, S::Error>>
where
Req: 'static,
S: Service<Cx, Req> + 'static,
{
let fut = S::call(unsafe { (raw as *mut S).as_mut().unwrap() }, cx, req);
Box::pin(fut)
}
#[cfg(feature = "service_send")]
fn clone<Cx, Req, S: Clone + Send + Service<Cx, Req> + 'static + Sync>(
raw: *mut (),
) -> BoxCloneService<Cx, Req, S::Response, S::Error>
where
Req: 'static,
{
BoxCloneService::new(S::clone(unsafe { (raw as *mut S).as_ref().unwrap() }))
}
#[cfg(not(feature = "service_send"))]
fn clone<Cx, Req, S: Clone + Service<Cx, Req> + 'static>(
raw: *mut (),
) -> BoxCloneService<Cx, Req, S::Response, S::Error>
where
Req: 'static,
{
BoxCloneService::new(S::clone(unsafe { (raw as *mut S).as_ref().unwrap() }))
}
fn drop<S>(raw: *mut ()) {
std::mem::drop(unsafe { Box::from_raw(raw as *mut S) });
}