rbdc_mysql/options/
parse.rs1use crate::options::MySqlConnectOptions;
2use percent_encoding::percent_decode_str;
3use rbdc::Error;
4use std::num::ParseIntError;
5use std::str::FromStr;
6use url::{ParseError, Url};
7
8impl FromStr for MySqlConnectOptions {
9 type Err = Error;
10
11 fn from_str(s: &str) -> Result<Self, Error> {
12 let url: Url = s
13 .parse()
14 .map_err(|e: ParseError| Error::from(e.to_string()))?;
15 let mut options = Self::new();
16
17 if let Some(host) = url.host_str() {
18 options = options.host(host);
19 }
20
21 if let Some(port) = url.port() {
22 options = options.port(port);
23 }
24
25 let username = url.username();
26 if !username.is_empty() {
27 options = options.username(&*percent_decode_str(username).decode_utf8()?);
28 }
29
30 if let Some(password) = url.password() {
31 options = options.password(&*percent_decode_str(password).decode_utf8()?);
32 }
33
34 let path = url.path().trim_start_matches('/');
35 if !path.is_empty() {
36 options = options.database(path);
37 }
38
39 for (key, value) in url.query_pairs().into_iter() {
40 match &*key {
41 "ssl-mode" => {
42 options = options.ssl_mode(value.parse()?);
43 }
44
45 "ssl-ca" => {
46 options = options.ssl_ca(&*value);
47 }
48
49 "charset" => {
50 options = options.charset(&*value);
51 }
52
53 "collation" => {
54 options = options.collation(&*value);
55 }
56
57 "statement-cache-capacity" => {
58 options = options.statement_cache_capacity(
59 value
60 .parse()
61 .map_err(|e: ParseIntError| Error::from(e.to_string()))?,
62 );
63 }
64
65 "socket" => {
66 options = options.socket(&*value);
67 }
68
69 _ => {}
70 }
71 }
72
73 Ok(options)
74 }
75}
76
77#[test]
78fn it_parses_username_with_at_sign_correctly() {
79 let uri = "mysql://user@hostname:password@hostname:5432/database";
80 let opts = MySqlConnectOptions::from_str(uri).unwrap();
81
82 assert_eq!("user@hostname", &opts.username);
83}
84
85#[test]
86fn it_parses_password_with_non_ascii_chars_correctly() {
87 let uri = "mysql://username:p@ssw0rd@hostname:5432/database";
88 let opts = MySqlConnectOptions::from_str(uri).unwrap();
89
90 assert_eq!(Some("p@ssw0rd".into()), opts.password);
91}