11use std:: collections:: hash_map:: { self , HashMap } ;
22use std:: iter;
3+ #[ cfg( all( feature = "runtime" , unix) ) ]
4+ use std:: path:: { Path , PathBuf } ;
35use std:: str:: { self , FromStr } ;
6+ #[ cfg( feature = "runtime" ) ]
7+ use std:: time:: Duration ;
48use tokio_io:: { AsyncRead , AsyncWrite } ;
59
610#[ cfg( feature = "runtime" ) ]
@@ -10,9 +14,24 @@ use crate::proto::HandshakeFuture;
1014use crate :: { Connect , MakeTlsMode , Socket } ;
1115use crate :: { Error , Handshake , TlsMode } ;
1216
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 ) ]
1426pub 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 > ,
1635}
1736
1837impl Default for Builder {
@@ -27,45 +46,80 @@ impl Builder {
2746 params. insert ( "client_encoding" . to_string ( ) , "UTF8" . to_string ( ) ) ;
2847 params. insert ( "timezone" . to_string ( ) , "GMT" . to_string ( ) ) ;
2948
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+ }
3159 }
3260
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
3573 }
3674
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
3982 }
4083
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
4388 }
4489
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) ;
4793 self
4894 }
4995
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
53107 }
54108
55109 pub fn handshake < S , T > ( & self , stream : S , tls_mode : T ) -> Handshake < S , T >
56110 where
57111 S : AsyncRead + AsyncWrite ,
58112 T : TlsMode < S > ,
59113 {
60- Handshake ( HandshakeFuture :: new ( stream, tls_mode, self . params . clone ( ) ) )
114+ Handshake ( HandshakeFuture :: new ( stream, tls_mode, self . clone ( ) ) )
61115 }
62116
63117 #[ cfg( feature = "runtime" ) ]
64118 pub fn connect < T > ( & self , make_tls_mode : T ) -> Connect < T >
65119 where
66120 T : MakeTlsMode < Socket > ,
67121 {
68- Connect ( ConnectFuture :: new ( make_tls_mode, self . params . clone ( ) ) )
122+ Connect ( ConnectFuture :: new ( make_tls_mode, self . clone ( ) ) )
69123 }
70124}
71125
@@ -77,7 +131,40 @@ impl FromStr for Builder {
77131 let mut builder = Builder :: new ( ) ;
78132
79133 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+ }
81168 }
82169
83170 Ok ( builder)
0 commit comments