Skip to main content

rama_net/client/
conn.rs

1use core::fmt;
2
3use rama_core::{Service, error::BoxError, extensions::ExtensionsRef, service::BoxService};
4
5#[derive(Clone)]
6/// The established connection to a server returned for the http client to be used.
7pub struct EstablishedClientConnection<S, Input> {
8    /// The `Input` for which a connection was established.
9    pub input: Input,
10    /// The established connection stream/service/... to the server.
11    pub conn: S,
12}
13
14impl<S: fmt::Debug, Input: fmt::Debug> fmt::Debug for EstablishedClientConnection<S, Input> {
15    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16        f.debug_struct("EstablishedClientConnection")
17            .field("input", &self.input)
18            .field("conn", &self.conn)
19            .finish()
20    }
21}
22
23/// Glue trait that is used as the Connector trait bound for
24/// clients establishing a connection on one layer or another.
25///
26/// Can also be manually implemented as an alternative [`Service`] trait,
27/// but from a Rama POV it is mostly used for UX trait bounds.
28pub trait ConnectorService<Input>: Send + Sync + 'static {
29    /// Connection returned by the [`ConnectorService`]
30    type Connection: Send + ExtensionsRef;
31    /// Error returned in case of connection / setup failure
32    type Error: Into<BoxError> + Send + 'static;
33
34    /// Establish a connection, which often involves some kind of handshake,
35    /// or connection revival.
36    fn connect(
37        &self,
38        input: Input,
39    ) -> impl Future<
40        Output = Result<EstablishedClientConnection<Self::Connection, Input>, Self::Error>,
41    > + Send
42    + '_;
43}
44
45impl<S, Input, Connection> ConnectorService<Input> for S
46where
47    S: Service<
48            Input,
49            Output = EstablishedClientConnection<Connection, Input>,
50            Error: Into<BoxError>,
51        >,
52    Connection: Send + ExtensionsRef,
53{
54    type Connection = Connection;
55    type Error = S::Error;
56
57    fn connect(
58        &self,
59        input: Input,
60    ) -> impl Future<
61        Output = Result<EstablishedClientConnection<Self::Connection, Input>, Self::Error>,
62    > + Send
63    + '_ {
64        self.serve(input)
65    }
66}
67
68/// A [`ConnectorService`] which only job is to [`Box`]
69/// the created [`Service`] by the inner [`ConnectorService`].
70#[derive(Debug, Clone)]
71pub struct BoxedConnectorService<S>(S);
72
73impl<S> BoxedConnectorService<S> {
74    /// Create a new [`BoxedConnectorService`].
75    pub fn new(connector: S) -> Self {
76        Self(connector)
77    }
78}
79
80impl<S, Input, Svc> Service<Input> for BoxedConnectorService<S>
81where
82    S: Service<Input, Output = EstablishedClientConnection<Svc, Input>, Error: Into<BoxError>>,
83    Svc: Service<Input>,
84    Input: Send + 'static,
85{
86    type Output = EstablishedClientConnection<BoxService<Input, Svc::Output, Svc::Error>, Input>;
87    type Error = S::Error;
88
89    async fn serve(&self, input: Input) -> Result<Self::Output, Self::Error> {
90        let EstablishedClientConnection { input, conn: svc } = self.0.serve(input).await?;
91        Ok(EstablishedClientConnection {
92            input,
93            conn: svc.boxed(),
94        })
95    }
96}