karyon_jsonrpc/client/
builder.rs1use std::sync::Arc;
2
3use karyon_core::async_runtime::Executor;
4use karyon_net::ToEndpoint;
5
6#[cfg(any(feature = "tcp", feature = "tls", feature = "quic"))]
7use karyon_net::Endpoint;
8
9#[cfg(feature = "quic")]
10use karyon_net::quic::ClientQuicConfig;
11#[cfg(feature = "tcp")]
12use karyon_net::tcp::TcpConfig;
13
14use crate::{
15 client::{
16 subscriptions::{default_notification_decoder, NotificationDecoder},
17 WsCodec,
18 },
19 codec::{JsonCodec, JsonRpcCodec},
20 error::Result,
21};
22
23#[cfg(any(feature = "tcp", feature = "tls", feature = "quic"))]
24use crate::error::Error;
25
26#[cfg(feature = "http")]
27use super::HttpConfig;
28use super::{Client, ClientConfig};
29
30const DEFAULT_TIMEOUT: u64 = 3000;
31const DEFAULT_MAX_SUBSCRIPTION_BUFFER_SIZE: usize = 20000;
32
33pub struct ClientBuilder<B, W = JsonCodec> {
54 inner: ClientConfig,
55 byte_codec: B,
56 ws_codec: W,
57 executor: Option<Executor>,
58}
59
60impl ClientBuilder<JsonCodec, JsonCodec> {
61 pub fn new(endpoint: impl ToEndpoint) -> Result<ClientBuilder<JsonCodec, JsonCodec>> {
63 ClientBuilder::new_with_codec(endpoint, JsonCodec::default())
64 }
65}
66
67impl<B: JsonRpcCodec> ClientBuilder<B, JsonCodec> {
68 pub fn new_with_codec(
72 endpoint: impl ToEndpoint,
73 codec: B,
74 ) -> Result<ClientBuilder<B, JsonCodec>> {
75 let endpoint = endpoint.to_endpoint()?;
76 Ok(ClientBuilder {
77 inner: ClientConfig {
78 endpoint,
79 timeout: Some(DEFAULT_TIMEOUT),
80 #[cfg(feature = "tcp")]
81 tcp_config: Default::default(),
82 #[cfg(feature = "tls")]
83 tls_config: None,
84 #[cfg(feature = "quic")]
85 quic_config: None,
86 #[cfg(feature = "http")]
87 http_config: HttpConfig::default(),
88 subscription_buffer_size: DEFAULT_MAX_SUBSCRIPTION_BUFFER_SIZE,
89 notification_decoder: default_notification_decoder,
90 },
91 byte_codec: codec,
92 ws_codec: JsonCodec::default(),
93 executor: None,
94 })
95 }
96}
97
98impl<B, W> ClientBuilder<B, W>
99where
100 B: JsonRpcCodec,
101 W: WsCodec,
102{
103 pub fn set_timeout(mut self, timeout: u64) -> Self {
105 self.inner.timeout = Some(timeout);
106 self
107 }
108
109 pub fn set_max_subscription_buffer_size(mut self, size: usize) -> Self {
111 self.inner.subscription_buffer_size = size;
112 self
113 }
114
115 pub fn with_notification_decoder(mut self, decoder: NotificationDecoder) -> Self {
118 self.inner.notification_decoder = decoder;
119 self
120 }
121
122 #[cfg(feature = "tcp")]
124 pub fn tcp_config(mut self, config: TcpConfig) -> Result<Self> {
125 match self.inner.endpoint {
126 Endpoint::Tcp(..) | Endpoint::Tls(..) | Endpoint::Ws(..) | Endpoint::Wss(..) => {
127 self.inner.tcp_config = config;
128 Ok(self)
129 }
130 _ => Err(Error::UnsupportedProtocol(self.inner.endpoint.to_string())),
131 }
132 }
133
134 #[cfg(feature = "tls")]
136 pub fn tls_config(mut self, config: karyon_net::tls::ClientTlsConfig) -> Result<Self> {
137 match self.inner.endpoint {
138 Endpoint::Tls(..) | Endpoint::Wss(..) => {
139 self.inner.tls_config = Some(config);
140 Ok(self)
141 }
142 _ => Err(Error::UnsupportedProtocol(format!(
143 "Invalid tls config for endpoint: {}",
144 self.inner.endpoint
145 ))),
146 }
147 }
148
149 #[cfg(feature = "quic")]
151 pub fn quic_config(mut self, config: ClientQuicConfig) -> Result<Self> {
152 match self.inner.endpoint {
153 Endpoint::Quic(..) => {
154 self.inner.quic_config = Some(config);
155 Ok(self)
156 }
157 #[cfg(feature = "http3")]
158 Endpoint::Http(..) => {
159 self.inner.quic_config = Some(config);
160 Ok(self)
161 }
162 _ => Err(Error::UnsupportedProtocol(format!(
163 "Invalid quic config for endpoint: {}",
164 self.inner.endpoint
165 ))),
166 }
167 }
168
169 #[cfg(feature = "http")]
171 pub fn http_config(mut self, config: HttpConfig) -> Result<Self> {
172 match self.inner.endpoint {
173 Endpoint::Http(..) => {
174 self.inner.http_config = config;
175 Ok(self)
176 }
177 _ => Err(Error::UnsupportedProtocol(format!(
178 "Invalid http config for endpoint: {}",
179 self.inner.endpoint
180 ))),
181 }
182 }
183
184 #[cfg(feature = "ws")]
187 pub fn with_ws_codec<W2: WsCodec>(self, ws_codec: W2) -> ClientBuilder<B, W2> {
188 ClientBuilder {
189 inner: self.inner,
190 byte_codec: self.byte_codec,
191 ws_codec,
192 executor: self.executor,
193 }
194 }
195
196 pub fn with_executor(mut self, ex: Executor) -> Self {
198 self.executor = Some(ex);
199 self
200 }
201
202 pub async fn build(self) -> Result<Arc<Client<B, W>>> {
204 Client::init(self.inner, self.byte_codec, self.ws_codec, self.executor).await
205 }
206}