use std::collections::HashMap;
use super::error::UrlError;
use percent_encoding::percent_decode;
use url::Url;
#[derive(Debug)]
pub struct ConnParams {
pub host: String,
pub port: u16,
pub username: String,
pub password: String,
pub db_name: String,
}
impl ConnParams {
pub fn from_url(s: &str) -> Result<(ConnParams, HashMap<String, String>), UrlError> {
let url = Url::parse(s)?;
if url.scheme() != "firebird" {
return Err(UrlError::UnsupportedScheme(url.scheme().to_string()));
}
if url.cannot_be_a_base() {
return Err(UrlError::BadUrl);
}
let host = url.host().unwrap().to_string();
let port = url.port().unwrap_or(3050);
let username = percent_decode(url.username().as_ref())
.decode_utf8_lossy()
.into_owned();
let password = percent_decode(url.password().unwrap().as_ref())
.decode_utf8_lossy()
.into_owned();
let mut db_name = percent_decode(url.path().as_ref())
.decode_utf8_lossy()
.into_owned();
let mut slash_count = 0;
for b in db_name.as_bytes() {
if b == &b'/' {
slash_count += 1;
}
}
if slash_count == 1 {
db_name = db_name[1..].to_string();
}
let mut options: HashMap<String, String> = url.query_pairs().into_owned().collect();
options
.entry(String::from("role"))
.or_insert("".to_string());
options
.entry(String::from("timezone"))
.or_insert("".to_string());
options
.entry(String::from("wire_crypt"))
.or_insert("true".to_string());
options
.entry(String::from("auth_plugin_name"))
.or_insert("Srp256".to_string());
options
.entry(String::from("page_size"))
.or_insert("4096".to_string());
Ok((
ConnParams {
host,
port,
username,
password,
db_name,
},
options,
))
}
}
#[test]
fn test_conn_params() {
let (params, _options) =
ConnParams::from_url("firebird://user:pass%20word@localhost:3051/foo/bar.fdb").unwrap();
assert_eq!(¶ms.host, "localhost");
assert_eq!(params.port, 3051u16);
assert_eq!(¶ms.username, "user");
assert_eq!(¶ms.password, "pass word");
assert_eq!(¶ms.db_name, "/foo/bar.fdb");
let (params, _options) = ConnParams::from_url("firebird://user:pass@foo/bar.fdb").unwrap();
assert_eq!(¶ms.host, "foo");
assert_eq!(params.port, 3050u16);
assert_eq!(¶ms.username, "user");
assert_eq!(¶ms.password, "pass");
assert_eq!(¶ms.db_name, "bar.fdb");
let (_params, options) =
ConnParams::from_url("firebird://user:pass@localhost/foo/bar.fdb?page_size=1234").unwrap();
assert_eq!(&options["page_size"], "1234");
}