xmtp_proto/traits/
boxed_client.rs1pub type BoxClient = Box<dyn BoxClientT>;
3
4#[derive(Clone)]
10pub struct ArcClient(Arc<dyn BoxClientT>);
11
12use bytes::Bytes;
13use http::{request, uri::PathAndQuery};
14use std::sync::Arc;
15
16use crate::api::{ApiClientError, BytesStream, IsConnectedCheck};
17
18use super::Client;
19
20struct BoxedClient<C: ?Sized> {
21 inner: C,
22}
23
24impl<C> BoxedClient<C> {
25 pub fn new(client: C) -> Self {
26 Self { inner: client }
27 }
28}
29
30pub trait BoxClientT: Client + IsConnectedCheck {}
31
32impl<T> BoxClientT for T where T: ?Sized + IsConnectedCheck + Client {}
33
34impl std::ops::Deref for ArcClient {
35 type Target = Arc<dyn BoxClientT>;
36
37 fn deref(&self) -> &Self::Target {
38 &self.0
39 }
40}
41
42impl From<Arc<dyn BoxClientT>> for ArcClient {
43 fn from(client: Arc<dyn BoxClientT>) -> Self {
44 Self(client)
45 }
46}
47
48#[xmtp_common::async_trait]
49impl Client for ArcClient {
50 fn host(&self) -> &str {
51 self.0.as_ref().host()
52 }
53
54 fn has_credential_source(&self) -> bool {
55 self.0.as_ref().has_credential_source()
56 }
57
58 async fn request(
59 &self,
60 request: request::Builder,
61 path: PathAndQuery,
62 body: Bytes,
63 ) -> Result<http::Response<Bytes>, ApiClientError> {
64 self.0.as_ref().request(request, path, body).await
65 }
66
67 async fn stream(
68 &self,
69 request: request::Builder,
70 path: PathAndQuery,
71 body: Bytes,
72 ) -> Result<http::Response<BytesStream>, ApiClientError> {
73 self.0.as_ref().stream(request, path, body).await
74 }
75
76 async fn bidi_stream(
77 &self,
78 request: request::Builder,
79 path: PathAndQuery,
80 body: xmtp_common::BoxDynStream<'static, Bytes>,
81 ) -> Result<http::Response<BytesStream>, ApiClientError> {
82 self.0.as_ref().bidi_stream(request, path, body).await
83 }
84
85 fn fake_stream(&self) -> http::Response<BytesStream> {
86 self.0.as_ref().fake_stream()
87 }
88}
89
90#[xmtp_common::async_trait]
91impl IsConnectedCheck for ArcClient {
92 async fn is_connected(&self) -> bool {
93 self.0.as_ref().is_connected().await
94 }
95}
96
97#[xmtp_common::async_trait]
98impl<C> Client for BoxedClient<C>
99where
100 C: Client,
101{
102 fn host(&self) -> &str {
103 self.inner.host()
104 }
105
106 fn has_credential_source(&self) -> bool {
107 self.inner.has_credential_source()
108 }
109
110 async fn request(
111 &self,
112 request: request::Builder,
113 path: PathAndQuery,
114 body: Bytes,
115 ) -> Result<http::Response<Bytes>, ApiClientError> {
116 self.inner.request(request, path, body).await
117 }
118
119 async fn stream(
120 &self,
121 request: request::Builder,
122 path: http::uri::PathAndQuery,
123 body: Bytes,
124 ) -> Result<http::Response<BytesStream>, ApiClientError> {
125 self.inner.stream(request, path, body).await
126 }
127
128 async fn bidi_stream(
129 &self,
130 request: request::Builder,
131 path: http::uri::PathAndQuery,
132 body: xmtp_common::BoxDynStream<'static, Bytes>,
133 ) -> Result<http::Response<BytesStream>, ApiClientError> {
134 self.inner.bidi_stream(request, path, body).await
135 }
136}
137
138pub trait ToBoxedClient {
139 fn boxed(self) -> BoxClient;
140 fn arced(self) -> ArcClient;
142}
143
144impl<C> ToBoxedClient for C
145where
146 C: Client + IsConnectedCheck + 'static,
147{
148 fn boxed(self) -> BoxClient {
149 Box::new(BoxedClient::new(self))
150 }
151 fn arced(self) -> ArcClient {
152 ArcClient(Arc::new(BoxedClient::new(self)))
153 }
154}
155
156#[xmtp_common::async_trait]
157impl<T> IsConnectedCheck for BoxedClient<T>
158where
159 T: ?Sized + IsConnectedCheck,
160{
161 async fn is_connected(&self) -> bool {
163 self.inner.is_connected().await
164 }
165}