#![forbid(unsafe_code)]
#![doc = include_str!("../README.md")]
use core::fmt;
use std::error::Error;
pub use use_db_name::DriverName;
macro_rules! driver_text_type {
($type_name:ident) => {
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct $type_name(String);
impl $type_name {
pub fn new(input: impl AsRef<str>) -> Result<Self, DriverError> {
validate_text(input.as_ref()).map(|value| Self(value.to_owned()))
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
}
impl fmt::Display for $type_name {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(self.as_str())
}
}
};
}
driver_text_type!(DriverVersion);
driver_text_type!(BackendName);
driver_text_type!(BackendFeature);
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum DriverCapability {
#[default]
Connect,
Transactions,
Pooling,
Migrations,
Other,
}
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum BackendKind {
#[default]
Sql,
Document,
KeyValue,
Graph,
Search,
Other,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum DriverError {
Empty,
ControlCharacter,
}
impl fmt::Display for DriverError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Empty => formatter.write_str("driver label cannot be empty"),
Self::ControlCharacter => {
formatter.write_str("driver label cannot contain control characters")
},
}
}
}
impl Error for DriverError {}
fn validate_text(input: &str) -> Result<&str, DriverError> {
if input.chars().any(char::is_control) {
return Err(DriverError::ControlCharacter);
}
let trimmed = input.trim();
if trimmed.is_empty() {
return Err(DriverError::Empty);
}
Ok(trimmed)
}
#[cfg(test)]
mod tests {
use super::{
BackendFeature, BackendKind, BackendName, DriverCapability, DriverName, DriverVersion,
};
#[test]
fn stores_driver_metadata() -> Result<(), Box<dyn std::error::Error>> {
let driver = DriverName::new("postgres")?;
let backend = BackendName::new("postgresql")?;
let version = DriverVersion::new("1.0")?;
let feature = BackendFeature::new("json")?;
assert_eq!(driver.as_str(), "postgres");
assert_eq!(backend.as_str(), "postgresql");
assert_eq!(version.as_str(), "1.0");
assert_eq!(feature.as_str(), "json");
assert_eq!(DriverCapability::default(), DriverCapability::Connect);
assert_eq!(BackendKind::default(), BackendKind::Sql);
Ok(())
}
}