distant_net/client/
builder.rs1mod tcp;
2pub use tcp::*;
3
4#[cfg(unix)]
5mod unix;
6
7#[cfg(unix)]
8pub use unix::*;
9
10#[cfg(windows)]
11mod windows;
12
13use std::time::Duration;
14use std::{convert, io};
15
16use async_trait::async_trait;
17use distant_auth::AuthHandler;
18#[cfg(windows)]
19pub use windows::*;
20
21use super::ClientConfig;
22use crate::client::{Client, UntypedClient};
23use crate::common::{Connection, Transport, Version};
24
25#[async_trait]
27pub trait Connector {
28 type Transport: Transport + 'static;
30
31 async fn connect(self) -> io::Result<Self::Transport>;
32}
33
34#[async_trait]
35impl<T: Transport + 'static> Connector for T {
36 type Transport = T;
37
38 async fn connect(self) -> io::Result<Self::Transport> {
39 Ok(self)
40 }
41}
42
43pub struct ClientBuilder<H, C> {
45 auth_handler: H,
46 connector: C,
47 config: ClientConfig,
48 connect_timeout: Option<Duration>,
49 version: Version,
50}
51
52impl<H, C> ClientBuilder<H, C> {
53 pub fn auth_handler<U>(self, auth_handler: U) -> ClientBuilder<U, C> {
55 ClientBuilder {
56 auth_handler,
57 config: self.config,
58 connector: self.connector,
59 connect_timeout: self.connect_timeout,
60 version: self.version,
61 }
62 }
63
64 pub fn config(self, config: ClientConfig) -> Self {
66 Self {
67 auth_handler: self.auth_handler,
68 config,
69 connector: self.connector,
70 connect_timeout: self.connect_timeout,
71 version: self.version,
72 }
73 }
74
75 pub fn connector<U>(self, connector: U) -> ClientBuilder<H, U> {
77 ClientBuilder {
78 auth_handler: self.auth_handler,
79 config: self.config,
80 connector,
81 connect_timeout: self.connect_timeout,
82 version: self.version,
83 }
84 }
85
86 pub fn connect_timeout(self, connect_timeout: impl Into<Option<Duration>>) -> Self {
88 Self {
89 auth_handler: self.auth_handler,
90 config: self.config,
91 connector: self.connector,
92 connect_timeout: connect_timeout.into(),
93 version: self.version,
94 }
95 }
96
97 pub fn version(self, version: Version) -> Self {
99 Self {
100 auth_handler: self.auth_handler,
101 config: self.config,
102 connector: self.connector,
103 connect_timeout: self.connect_timeout,
104 version,
105 }
106 }
107}
108
109impl ClientBuilder<(), ()> {
110 pub fn new() -> Self {
111 Self {
112 auth_handler: (),
113 config: Default::default(),
114 connector: (),
115 connect_timeout: None,
116 version: Default::default(),
117 }
118 }
119}
120
121impl Default for ClientBuilder<(), ()> {
122 fn default() -> Self {
123 Self::new()
124 }
125}
126
127impl<H, C> ClientBuilder<H, C>
128where
129 H: AuthHandler + Send,
130 C: Connector,
131{
132 pub async fn connect_untyped(self) -> io::Result<UntypedClient> {
136 let auth_handler = self.auth_handler;
137 let config = self.config;
138 let connect_timeout = self.connect_timeout;
139 let version = self.version;
140
141 let f = async move {
142 let transport = match connect_timeout {
143 Some(duration) => tokio::time::timeout(duration, self.connector.connect())
144 .await
145 .map_err(|x| io::Error::new(io::ErrorKind::TimedOut, x))
146 .and_then(convert::identity)?,
147 None => self.connector.connect().await?,
148 };
149 let connection = Connection::client(transport, auth_handler, version).await?;
150 Ok(UntypedClient::spawn(connection, config))
151 };
152
153 match connect_timeout {
154 Some(duration) => tokio::time::timeout(duration, f)
155 .await
156 .map_err(|x| io::Error::new(io::ErrorKind::TimedOut, x))
157 .and_then(convert::identity),
158 None => f.await,
159 }
160 }
161
162 pub async fn connect<T, U>(self) -> io::Result<Client<T, U>> {
166 Ok(self.connect_untyped().await?.into_typed_client())
167 }
168}