1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4use core::fmt;
7use std::error::Error;
8
9pub use use_db_name::DriverName;
10
11macro_rules! driver_text_type {
12 ($type_name:ident) => {
13 #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
14 pub struct $type_name(String);
15
16 impl $type_name {
17 pub fn new(input: impl AsRef<str>) -> Result<Self, DriverError> {
23 validate_text(input.as_ref()).map(|value| Self(value.to_owned()))
24 }
25
26 #[must_use]
28 pub fn as_str(&self) -> &str {
29 &self.0
30 }
31 }
32
33 impl fmt::Display for $type_name {
34 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
35 formatter.write_str(self.as_str())
36 }
37 }
38 };
39}
40
41driver_text_type!(DriverVersion);
42driver_text_type!(BackendName);
43driver_text_type!(BackendFeature);
44
45#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
47pub enum DriverCapability {
48 #[default]
50 Connect,
51 Transactions,
53 Pooling,
55 Migrations,
57 Other,
59}
60
61#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
63pub enum BackendKind {
64 #[default]
66 Sql,
67 Document,
69 KeyValue,
71 Graph,
73 Search,
75 Other,
77}
78
79#[derive(Clone, Copy, Debug, Eq, PartialEq)]
81pub enum DriverError {
82 Empty,
84 ControlCharacter,
86}
87
88impl fmt::Display for DriverError {
89 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
90 match self {
91 Self::Empty => formatter.write_str("driver label cannot be empty"),
92 Self::ControlCharacter => {
93 formatter.write_str("driver label cannot contain control characters")
94 },
95 }
96 }
97}
98
99impl Error for DriverError {}
100
101fn validate_text(input: &str) -> Result<&str, DriverError> {
102 if input.chars().any(char::is_control) {
103 return Err(DriverError::ControlCharacter);
104 }
105 let trimmed = input.trim();
106 if trimmed.is_empty() {
107 return Err(DriverError::Empty);
108 }
109 Ok(trimmed)
110}
111
112#[cfg(test)]
113mod tests {
114 use super::{
115 BackendFeature, BackendKind, BackendName, DriverCapability, DriverName, DriverVersion,
116 };
117
118 #[test]
119 fn stores_driver_metadata() -> Result<(), Box<dyn std::error::Error>> {
120 let driver = DriverName::new("postgres")?;
121 let backend = BackendName::new("postgresql")?;
122 let version = DriverVersion::new("1.0")?;
123 let feature = BackendFeature::new("json")?;
124
125 assert_eq!(driver.as_str(), "postgres");
126 assert_eq!(backend.as_str(), "postgresql");
127 assert_eq!(version.as_str(), "1.0");
128 assert_eq!(feature.as_str(), "json");
129 assert_eq!(DriverCapability::default(), DriverCapability::Connect);
130 assert_eq!(BackendKind::default(), BackendKind::Sql);
131 Ok(())
132 }
133}