1use rama_core::{Context, Service, error::BoxError, service::BoxService};
2use std::fmt;
3
4pub struct EstablishedClientConnection<S, State, Request> {
6    pub ctx: Context<State>,
8    pub req: Request,
10    pub conn: S,
12}
13
14impl<S: fmt::Debug, State: fmt::Debug, Request: fmt::Debug> fmt::Debug
15    for EstablishedClientConnection<S, State, Request>
16{
17    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18        f.debug_struct("EstablishedClientConnection")
19            .field("ctx", &self.ctx)
20            .field("req", &self.req)
21            .field("conn", &self.conn)
22            .finish()
23    }
24}
25
26impl<S: Clone, State: Clone, Request: Clone> Clone
27    for EstablishedClientConnection<S, State, Request>
28{
29    fn clone(&self) -> Self {
30        Self {
31            ctx: self.ctx.clone(),
32            req: self.req.clone(),
33            conn: self.conn.clone(),
34        }
35    }
36}
37
38pub trait ConnectorService<State, Request>: Send + Sync + 'static {
44    type Connection;
46    type Error: Into<BoxError>;
48
49    fn connect(
52        &self,
53        ctx: Context<State>,
54        req: Request,
55    ) -> impl Future<
56        Output = Result<EstablishedClientConnection<Self::Connection, State, Request>, Self::Error>,
57    > + Send
58    + '_;
59}
60
61impl<S, State, Request, Connection> ConnectorService<State, Request> for S
62where
63    S: Service<
64            State,
65            Request,
66            Response = EstablishedClientConnection<Connection, State, Request>,
67            Error: Into<BoxError>,
68        >,
69{
70    type Connection = Connection;
71    type Error = S::Error;
72
73    fn connect(
74        &self,
75        ctx: Context<State>,
76        req: Request,
77    ) -> impl Future<
78        Output = Result<EstablishedClientConnection<Self::Connection, State, Request>, Self::Error>,
79    > + Send
80    + '_ {
81        self.serve(ctx, req)
82    }
83}
84
85pub struct BoxedConnectorService<S>(S);
88
89impl<S> BoxedConnectorService<S> {
90    pub fn new(connector: S) -> Self {
92        Self(connector)
93    }
94}
95
96impl<S: fmt::Debug> fmt::Debug for BoxedConnectorService<S> {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        f.debug_tuple("BoxedConnectorService")
99            .field(&self.0)
100            .finish()
101    }
102}
103
104impl<S: Clone> Clone for BoxedConnectorService<S> {
105    fn clone(&self) -> Self {
106        Self(self.0.clone())
107    }
108}
109
110impl<S, State, Request, Svc> Service<State, Request> for BoxedConnectorService<S>
111where
112    S: Service<
113            State,
114            Request,
115            Response = EstablishedClientConnection<Svc, State, Request>,
116            Error: Into<BoxError>,
117        >,
118    Svc: Service<State, Request>,
119    State: Send + 'static,
120    Request: Send + 'static,
121{
122    type Response = EstablishedClientConnection<
123        BoxService<State, Request, Svc::Response, Svc::Error>,
124        State,
125        Request,
126    >;
127    type Error = S::Error;
128
129    async fn serve(
130        &self,
131        ctx: Context<State>,
132        req: Request,
133    ) -> Result<Self::Response, Self::Error> {
134        let EstablishedClientConnection {
135            ctx,
136            req,
137            conn: svc,
138        } = self.0.serve(ctx, req).await?;
139        Ok(EstablishedClientConnection {
140            ctx,
141            req,
142            conn: svc.boxed(),
143        })
144    }
145}