1
1
use std:: collections:: hash_map:: { self , HashMap } ;
2
2
use std:: iter;
3
+ #[ cfg( all( feature = "runtime" , unix) ) ]
4
+ use std:: path:: { Path , PathBuf } ;
3
5
use std:: str:: { self , FromStr } ;
6
+ #[ cfg( feature = "runtime" ) ]
7
+ use std:: time:: Duration ;
4
8
use tokio_io:: { AsyncRead , AsyncWrite } ;
5
9
6
10
#[ cfg( feature = "runtime" ) ]
@@ -10,9 +14,24 @@ use crate::proto::HandshakeFuture;
10
14
use crate :: { Connect , MakeTlsMode , Socket } ;
11
15
use crate :: { Error , Handshake , TlsMode } ;
12
16
13
- #[ derive( Clone ) ]
17
+ #[ cfg( feature = "runtime" ) ]
18
+ #[ derive( Debug , Clone , PartialEq ) ]
19
+ pub ( crate ) enum Host {
20
+ Tcp ( String ) ,
21
+ #[ cfg( unix) ]
22
+ Unix ( PathBuf ) ,
23
+ }
24
+
25
+ #[ derive( Debug , Clone , PartialEq ) ]
14
26
pub struct Builder {
15
- params : HashMap < String , String > ,
27
+ pub ( crate ) params : HashMap < String , String > ,
28
+ pub ( crate ) password : Option < Vec < u8 > > ,
29
+ #[ cfg( feature = "runtime" ) ]
30
+ pub ( crate ) host : Vec < Host > ,
31
+ #[ cfg( feature = "runtime" ) ]
32
+ pub ( crate ) port : Vec < u16 > ,
33
+ #[ cfg( feature = "runtime" ) ]
34
+ pub ( crate ) connect_timeout : Option < Duration > ,
16
35
}
17
36
18
37
impl Default for Builder {
@@ -27,45 +46,80 @@ impl Builder {
27
46
params. insert ( "client_encoding" . to_string ( ) , "UTF8" . to_string ( ) ) ;
28
47
params. insert ( "timezone" . to_string ( ) , "GMT" . to_string ( ) ) ;
29
48
30
- Builder { params }
49
+ Builder {
50
+ params,
51
+ password : None ,
52
+ #[ cfg( feature = "runtime" ) ]
53
+ host : vec ! [ ] ,
54
+ #[ cfg( feature = "runtime" ) ]
55
+ port : vec ! [ ] ,
56
+ #[ cfg( feature = "runtime" ) ]
57
+ connect_timeout : None ,
58
+ }
31
59
}
32
60
33
- pub fn user ( & mut self , user : & str ) -> & mut Builder {
34
- self . param ( "user" , user)
61
+ #[ cfg( feature = "runtime" ) ]
62
+ pub fn host ( & mut self , host : & str ) -> & mut Builder {
63
+ #[ cfg( unix) ]
64
+ {
65
+ if host. starts_with ( '/' ) {
66
+ self . host . push ( Host :: Unix ( PathBuf :: from ( host) ) ) ;
67
+ return self ;
68
+ }
69
+ }
70
+
71
+ self . host . push ( Host :: Tcp ( host. to_string ( ) ) ) ;
72
+ self
35
73
}
36
74
37
- pub fn dbname ( & mut self , database : & str ) -> & mut Builder {
38
- self . param ( "dbname" , database)
75
+ #[ cfg( all( feature = "runtime" , unix) ) ]
76
+ pub fn host_path < T > ( & mut self , host : T ) -> & mut Builder
77
+ where
78
+ T : AsRef < Path > ,
79
+ {
80
+ self . host . push ( Host :: Unix ( host. as_ref ( ) . to_path_buf ( ) ) ) ;
81
+ self
39
82
}
40
83
41
- pub fn password ( & mut self , password : & str ) -> & mut Builder {
42
- self . param ( "password" , password)
84
+ #[ cfg( feature = "runtime" ) ]
85
+ pub fn port ( & mut self , port : u16 ) -> & mut Builder {
86
+ self . port . push ( port) ;
87
+ self
43
88
}
44
89
45
- pub fn param ( & mut self , key : & str , value : & str ) -> & mut Builder {
46
- self . params . insert ( key. to_string ( ) , value. to_string ( ) ) ;
90
+ #[ cfg( feature = "runtime" ) ]
91
+ pub fn connect_timeout ( & mut self , connect_timeout : Duration ) -> & mut Builder {
92
+ self . connect_timeout = Some ( connect_timeout) ;
47
93
self
48
94
}
49
95
50
- /// FIXME do we want this?
51
- pub fn iter ( & self ) -> Iter < ' _ > {
52
- Iter ( self . params . iter ( ) )
96
+ pub fn password < T > ( & mut self , password : T ) -> & mut Builder
97
+ where
98
+ T : AsRef < [ u8 ] > ,
99
+ {
100
+ self . password = Some ( password. as_ref ( ) . to_vec ( ) ) ;
101
+ self
102
+ }
103
+
104
+ pub fn param ( & mut self , key : & str , value : & str ) -> & mut Builder {
105
+ self . params . insert ( key. to_string ( ) , value. to_string ( ) ) ;
106
+ self
53
107
}
54
108
55
109
pub fn handshake < S , T > ( & self , stream : S , tls_mode : T ) -> Handshake < S , T >
56
110
where
57
111
S : AsyncRead + AsyncWrite ,
58
112
T : TlsMode < S > ,
59
113
{
60
- Handshake ( HandshakeFuture :: new ( stream, tls_mode, self . params . clone ( ) ) )
114
+ Handshake ( HandshakeFuture :: new ( stream, tls_mode, self . clone ( ) ) )
61
115
}
62
116
63
117
#[ cfg( feature = "runtime" ) ]
64
118
pub fn connect < T > ( & self , make_tls_mode : T ) -> Connect < T >
65
119
where
66
120
T : MakeTlsMode < Socket > ,
67
121
{
68
- Connect ( ConnectFuture :: new ( make_tls_mode, self . params . clone ( ) ) )
122
+ Connect ( ConnectFuture :: new ( make_tls_mode, self . clone ( ) ) )
69
123
}
70
124
}
71
125
@@ -77,7 +131,40 @@ impl FromStr for Builder {
77
131
let mut builder = Builder :: new ( ) ;
78
132
79
133
while let Some ( ( key, value) ) = parser. parameter ( ) ? {
80
- builder. params . insert ( key. to_string ( ) , value) ;
134
+ match key {
135
+ "password" => {
136
+ builder. password ( value) ;
137
+ }
138
+ #[ cfg( feature = "runtime" ) ]
139
+ "host" => {
140
+ for host in value. split ( ',' ) {
141
+ builder. host ( host) ;
142
+ }
143
+ }
144
+ #[ cfg( feature = "runtime" ) ]
145
+ "port" => {
146
+ for port in value. split ( ',' ) {
147
+ let port = if port. is_empty ( ) {
148
+ 5432
149
+ } else {
150
+ port. parse ( ) . map_err ( Error :: invalid_port) ?
151
+ } ;
152
+ builder. port ( port) ;
153
+ }
154
+ }
155
+ #[ cfg( feature = "runtime" ) ]
156
+ "connect_timeout" => {
157
+ let timeout = value
158
+ . parse :: < i64 > ( )
159
+ . map_err ( Error :: invalid_connect_timeout) ?;
160
+ if timeout > 0 {
161
+ builder. connect_timeout ( Duration :: from_secs ( timeout as u64 ) ) ;
162
+ }
163
+ }
164
+ key => {
165
+ builder. param ( key, & value) ;
166
+ }
167
+ }
81
168
}
82
169
83
170
Ok ( builder)
0 commit comments