#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(
feature = "serde",
derive(serde::Deserialize, serde::Serialize),
serde(default, rename_all = "snake_case")
)]
pub struct DatabaseUriSchema {
pub(crate) prefix: String,
pub(crate) host: String,
pub(crate) port: u16,
pub(crate) user: String,
pub(crate) password: String,
pub(crate) database: String,
}
impl DatabaseUriSchema {
pub fn from_parts(
prefix: impl ToString,
host: impl ToString,
port: u16,
user: impl ToString,
password: impl ToString,
database: impl ToString,
) -> Self {
Self {
prefix: prefix.to_string(),
host: host.to_string(),
port,
user: user.to_string(),
password: password.to_string(),
database: database.to_string(),
}
}
pub fn postgresql(
host: impl ToString,
port: u16,
user: impl ToString,
password: impl ToString,
database: impl ToString,
) -> Self {
Self::from_parts("postgresql", host, port, user, password, database)
}
pub fn as_uri_string(&self) -> String {
format!(
"{prefix}://{user}:{password}@{host}:{port}/{database}",
prefix = self.prefix,
user = self.user,
password = self.password,
host = self.host,
port = self.port,
database = self.database
)
}
pub const fn prefix(&self) -> &String {
&self.prefix
}
pub const fn prefix_mut(&mut self) -> &mut String {
&mut self.prefix
}
#[inline]
pub fn host(&self) -> &String {
&self.host
}
pub const fn host_mut(&mut self) -> &mut String {
&mut self.host
}
pub const fn port(&self) -> u16 {
self.port
}
pub const fn port_mut(&mut self) -> &mut u16 {
&mut self.port
}
pub const fn user(&self) -> &String {
&self.user
}
pub const fn user_mut(&mut self) -> &mut String {
&mut self.user
}
pub const fn password(&self) -> &String {
&self.password
}
pub const fn password_mut(&mut self) -> &mut String {
&mut self.password
}
pub const fn database(&self) -> &String {
&self.database
}
pub const fn database_mut(&mut self) -> &mut String {
&mut self.database
}
#[inline]
pub fn set_database<U: ToString>(&mut self, value: U) -> &mut Self {
*self.database_mut() = value.to_string();
self
}
#[inline]
pub fn set_host(&mut self, host: impl ToString) -> &mut Self {
self.host = host.to_string();
self
}
#[inline]
pub fn set_password<U: ToString>(&mut self, value: U) -> &mut Self {
*self.password_mut() = value.to_string();
self
}
#[inline]
pub fn set_port(&mut self, port: u16) -> &mut Self {
self.port = port;
self
}
#[inline]
pub fn set_prefix<U: ToString>(&mut self, value: U) -> &mut Self {
*self.prefix_mut() = value.to_string();
self
}
#[inline]
pub fn set_user<U: ToString>(&mut self, value: U) -> &mut Self {
*self.user_mut() = value.to_string();
self
}
pub fn with_database<U: ToString>(self, value: U) -> Self {
Self {
database: value.to_string(),
..self
}
}
pub fn with_host<U: ToString>(self, value: U) -> Self {
Self {
host: value.to_string(),
..self
}
}
pub fn with_password<U: ToString>(self, value: U) -> Self {
Self {
password: value.to_string(),
..self
}
}
pub fn with_port(self, value: u16) -> Self {
Self {
port: value,
..self
}
}
pub fn with_prefix<U: ToString>(self, value: U) -> Self {
Self {
prefix: value.to_string(),
..self
}
}
pub fn with_user<U: ToString>(self, value: U) -> Self {
Self {
user: value.to_string(),
..self
}
}
}
impl Default for DatabaseUriSchema {
fn default() -> Self {
Self::postgresql("localhost", 5432, "postgres", "postgres", "postgres")
}
}
impl core::fmt::Display for DatabaseUriSchema {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.write_str(&self.as_uri_string())
}
}
#[cfg(feature = "url")]
impl core::str::FromStr for DatabaseUriSchema {
type Err = crate::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut schema: DatabaseUriSchema = Self::default();
let url = url::Url::parse(s)?;
schema.host = url
.host_str()
.ok_or(url::ParseError::EmptyHost)?
.to_string();
schema.port = url.port().unwrap_or(5432);
schema.user = url.username().to_string();
schema.password = url.password().unwrap_or("").to_string();
schema.database = url.path().trim_start_matches('/').to_string();
schema.prefix = url.scheme().to_string();
Ok(schema)
}
}