use crate::error::SqlError;
use indexmap::IndexMap;
use secrecy::SecretString;
use url::Url;
#[derive(Debug, Clone)]
pub struct DatabaseUrl {
raw: String,
parsed: Url,
}
impl DatabaseUrl {
pub fn parse(raw: &str) -> Result<Self, SqlError> {
let parsed = Url::parse(raw).map_err(|e| SqlError::InvalidUrl(format!("{e}")))?;
Ok(Self {
raw: raw.to_string(),
parsed,
})
}
pub fn scheme(&self) -> &str {
self.parsed.scheme()
}
pub fn username(&self) -> &str {
self.parsed.username()
}
pub fn password(&self) -> Option<SecretString> {
self.parsed.password().map(|p| SecretString::new(p.into()))
}
pub fn host(&self) -> Option<&str> {
self.parsed.host_str()
}
pub fn port(&self) -> Option<u16> {
self.parsed.port()
}
pub fn path(&self) -> &str {
self.parsed.path()
}
pub fn database(&self) -> &str {
self.parsed.path().trim_start_matches('/')
}
pub fn set_password(&mut self, password: Option<&str>) {
let _ = self.parsed.set_password(password);
}
pub fn params(&self) -> IndexMap<String, String> {
self.parsed
.query_pairs()
.map(|(k, v)| (k.into_owned(), v.into_owned()))
.collect()
}
pub fn redacted(&self) -> String {
let mut url = self.parsed.clone();
let _ = url.set_password(Some("***"));
url.to_string()
}
pub fn as_str(&self) -> &str {
&self.raw
}
pub fn raw(&self) -> &str {
&self.raw
}
}