use core::fmt;
use rama_core::{Service, error::BoxError, extensions::ExtensionsRef, service::BoxService};
#[derive(Clone)]
pub struct EstablishedClientConnection<S, Input> {
pub input: Input,
pub conn: S,
}
impl<S: fmt::Debug, Input: fmt::Debug> fmt::Debug for EstablishedClientConnection<S, Input> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EstablishedClientConnection")
.field("input", &self.input)
.field("conn", &self.conn)
.finish()
}
}
pub trait ConnectorService<Input>: Send + Sync + 'static {
type Connection: Send + ExtensionsRef;
type Error: Into<BoxError> + Send + 'static;
fn connect(
&self,
input: Input,
) -> impl Future<
Output = Result<EstablishedClientConnection<Self::Connection, Input>, Self::Error>,
> + Send
+ '_;
}
impl<S, Input, Connection> ConnectorService<Input> for S
where
S: Service<
Input,
Output = EstablishedClientConnection<Connection, Input>,
Error: Into<BoxError>,
>,
Connection: Send + ExtensionsRef,
{
type Connection = Connection;
type Error = S::Error;
fn connect(
&self,
input: Input,
) -> impl Future<
Output = Result<EstablishedClientConnection<Self::Connection, Input>, Self::Error>,
> + Send
+ '_ {
self.serve(input)
}
}
#[derive(Debug, Clone)]
pub struct BoxedConnectorService<S>(S);
impl<S> BoxedConnectorService<S> {
pub fn new(connector: S) -> Self {
Self(connector)
}
}
impl<S, Input, Svc> Service<Input> for BoxedConnectorService<S>
where
S: Service<Input, Output = EstablishedClientConnection<Svc, Input>, Error: Into<BoxError>>,
Svc: Service<Input>,
Input: Send + 'static,
{
type Output = EstablishedClientConnection<BoxService<Input, Svc::Output, Svc::Error>, Input>;
type Error = S::Error;
async fn serve(&self, input: Input) -> Result<Self::Output, Self::Error> {
let EstablishedClientConnection { input, conn: svc } = self.0.serve(input).await?;
Ok(EstablishedClientConnection {
input,
conn: svc.boxed(),
})
}
}