|
1 | | -//! Postgres connection parameters. |
2 | | -
|
| 1 | +//! Connection parameters |
3 | 2 | use std::error::Error; |
4 | | -use std::path::{Path, PathBuf}; |
5 | | -use std::mem; |
| 3 | +use std::path::PathBuf; |
6 | 4 |
|
7 | 5 | use params::url::Url; |
8 | 6 |
|
9 | 7 | mod url; |
10 | 8 |
|
11 | | -/// The host. |
| 9 | +/// Specifies the target server to connect to. |
12 | 10 | #[derive(Clone, Debug)] |
13 | | -pub enum Host { |
14 | | - /// A TCP hostname. |
| 11 | +pub enum ConnectTarget { |
| 12 | + /// Connect via TCP to the specified host. |
15 | 13 | Tcp(String), |
16 | | - |
17 | | - /// The path to a directory containing the server's Unix socket. |
| 14 | + /// Connect via a Unix domain socket in the specified directory. |
| 15 | + /// |
| 16 | + /// Unix sockets are only supported on Unixy platforms (i.e. not Windows). |
18 | 17 | Unix(PathBuf), |
19 | 18 | } |
20 | 19 |
|
21 | 20 | /// Authentication information. |
22 | 21 | #[derive(Clone, Debug)] |
23 | | -pub struct User { |
24 | | - name: String, |
25 | | - password: Option<String>, |
26 | | -} |
27 | | - |
28 | | -impl User { |
| 22 | +pub struct UserInfo { |
29 | 23 | /// The username. |
30 | | - pub fn name(&self) -> &str { |
31 | | - &self.name |
32 | | - } |
33 | | - |
| 24 | + pub user: String, |
34 | 25 | /// An optional password. |
35 | | - pub fn password(&self) -> Option<&str> { |
36 | | - self.password.as_ref().map(|p| &**p) |
37 | | - } |
| 26 | + pub password: Option<String>, |
38 | 27 | } |
39 | 28 |
|
40 | 29 | /// Information necessary to open a new connection to a Postgres server. |
41 | 30 | #[derive(Clone, Debug)] |
42 | 31 | pub struct ConnectParams { |
43 | | - host: Host, |
44 | | - port: u16, |
45 | | - user: Option<User>, |
46 | | - database: Option<String>, |
47 | | - options: Vec<(String, String)>, |
48 | | -} |
49 | | - |
50 | | -impl ConnectParams { |
51 | | - /// Returns a new builder. |
52 | | - pub fn builder() -> Builder { |
53 | | - Builder { |
54 | | - port: 5432, |
55 | | - user: None, |
56 | | - database: None, |
57 | | - options: vec![], |
58 | | - } |
59 | | - } |
60 | | - |
61 | 32 | /// The target server. |
62 | | - pub fn host(&self) -> &Host { |
63 | | - &self.host |
64 | | - } |
65 | | - |
| 33 | + pub target: ConnectTarget, |
66 | 34 | /// The target port. |
67 | 35 | /// |
68 | | - /// Defaults to 5432. |
69 | | - pub fn port(&self) -> u16 { |
70 | | - self.port |
71 | | - } |
72 | | - |
| 36 | + /// Defaults to 5432 if not specified. |
| 37 | + pub port: Option<u16>, |
73 | 38 | /// The user to login as. |
74 | 39 | /// |
75 | | - /// Connection requires a user but query cancellation does not. |
76 | | - pub fn user(&self) -> Option<&User> { |
77 | | - self.user.as_ref() |
78 | | - } |
79 | | - |
| 40 | + /// `Connection::connect` requires a user but `cancel_query` does not. |
| 41 | + pub user: Option<UserInfo>, |
80 | 42 | /// The database to connect to. |
81 | 43 | /// |
82 | | - /// Defaults to the username. |
83 | | - pub fn database(&self) -> Option<&str> { |
84 | | - self.database.as_ref().map(|d| &**d) |
85 | | - } |
86 | | - |
| 44 | + /// Defaults the value of `user`. |
| 45 | + pub database: Option<String>, |
87 | 46 | /// Runtime parameters to be passed to the Postgres backend. |
88 | | - pub fn options(&self) -> &[(String, String)] { |
89 | | - &self.options |
90 | | - } |
91 | | -} |
92 | | - |
93 | | -/// A builder type for `ConnectParams`. |
94 | | -pub struct Builder { |
95 | | - port: u16, |
96 | | - user: Option<User>, |
97 | | - database: Option<String>, |
98 | | - options: Vec<(String, String)>, |
99 | | -} |
100 | | - |
101 | | -impl Builder { |
102 | | - pub fn port(&mut self, port: u16) -> &mut Builder { |
103 | | - self.port = port; |
104 | | - self |
105 | | - } |
106 | | - |
107 | | - pub fn user(&mut self, name: &str, password: Option<&str>) -> &mut Builder { |
108 | | - self.user = Some(User { |
109 | | - name: name.to_owned(), |
110 | | - password: password.map(ToOwned::to_owned), |
111 | | - }); |
112 | | - self |
113 | | - } |
114 | | - |
115 | | - pub fn database(&mut self, database: &str) -> &mut Builder { |
116 | | - self.database = Some(database.to_owned()); |
117 | | - self |
118 | | - } |
119 | | - |
120 | | - pub fn option(&mut self, name: &str, value: &str) -> &mut Builder { |
121 | | - self.options.push((name.to_owned(), value.to_owned())); |
122 | | - self |
123 | | - } |
124 | | - |
125 | | - pub fn build_tcp(&mut self, host: &str) -> ConnectParams { |
126 | | - self.build(Host::Tcp(host.to_owned())) |
127 | | - } |
128 | | - |
129 | | - pub fn build_unix<P>(&mut self, host: P) -> ConnectParams |
130 | | - where P: AsRef<Path> |
131 | | - { |
132 | | - self.build(Host::Unix(host.as_ref().to_owned())) |
133 | | - } |
134 | | - |
135 | | - pub fn build(&mut self, host: Host) -> ConnectParams { |
136 | | - ConnectParams { |
137 | | - host: host, |
138 | | - port: self.port, |
139 | | - database: self.database.take(), |
140 | | - user: self.user.take(), |
141 | | - options: mem::replace(&mut self.options, vec![]), |
142 | | - } |
143 | | - } |
| 47 | + pub options: Vec<(String, String)>, |
144 | 48 | } |
145 | 49 |
|
146 | 50 | /// A trait implemented by types that can be converted into a `ConnectParams`. |
@@ -172,32 +76,37 @@ impl IntoConnectParams for String { |
172 | 76 |
|
173 | 77 | impl IntoConnectParams for Url { |
174 | 78 | fn into_connect_params(self) -> Result<ConnectParams, Box<Error + Sync + Send>> { |
175 | | - let Url { host, port, user, path: url::Path { path, query: options, .. }, .. } = self; |
176 | | - |
177 | | - let mut builder = ConnectParams::builder(); |
178 | | - |
179 | | - if let Some(port) = port { |
180 | | - builder.port(port); |
181 | | - } |
182 | | - |
183 | | - if let Some(info) = user { |
184 | | - builder.user(&info.user, info.pass.as_ref().map(|p| &**p)); |
185 | | - } |
186 | | - |
187 | | - if !path.is_empty() { |
188 | | - // path contains the leading / |
189 | | - builder.database(&path[1..]); |
190 | | - } |
191 | | - |
192 | | - for (name, value) in options { |
193 | | - builder.option(&name, &value); |
194 | | - } |
| 79 | + let Url { host, port, user, path: url::Path { mut path, query: options, .. }, .. } = self; |
195 | 80 |
|
196 | 81 | let maybe_path = try!(url::decode_component(&host)); |
197 | | - if maybe_path.starts_with('/') { |
198 | | - Ok(builder.build_unix(maybe_path)) |
| 82 | + let target = if maybe_path.starts_with('/') { |
| 83 | + ConnectTarget::Unix(PathBuf::from(maybe_path)) |
199 | 84 | } else { |
200 | | - Ok(builder.build_tcp(&maybe_path)) |
201 | | - } |
| 85 | + ConnectTarget::Tcp(host) |
| 86 | + }; |
| 87 | + |
| 88 | + let user = user.map(|url::UserInfo { user, pass }| { |
| 89 | + UserInfo { |
| 90 | + user: user, |
| 91 | + password: pass, |
| 92 | + } |
| 93 | + }); |
| 94 | + |
| 95 | + let database = if path.is_empty() { |
| 96 | + None |
| 97 | + } else { |
| 98 | + // path contains the leading / |
| 99 | + path.remove(0); |
| 100 | + Some(path) |
| 101 | + }; |
| 102 | + |
| 103 | + Ok(ConnectParams { |
| 104 | + target: target, |
| 105 | + port: port, |
| 106 | + user: user, |
| 107 | + database: database, |
| 108 | + options: options, |
| 109 | + }) |
202 | 110 | } |
203 | 111 | } |
| 112 | + |
0 commit comments