use std::fmt;
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(transparent)]
#[cfg_attr(feature = "schema", schemars(transparent))]
pub struct TableName(String);
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(transparent)]
#[cfg_attr(feature = "schema", schemars(transparent))]
pub struct ColumnName(String);
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(transparent)]
#[cfg_attr(feature = "schema", schemars(transparent))]
pub struct IndexName(String);
macro_rules! impl_name_newtype {
($ty:ident) => {
impl $ty {
#[must_use]
pub fn new(s: impl Into<String>) -> Self {
Self(s.into())
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
#[must_use]
pub fn into_inner(self) -> String {
self.0
}
}
impl From<String> for $ty {
fn from(s: String) -> Self {
Self(s)
}
}
impl From<&str> for $ty {
fn from(s: &str) -> Self {
Self(s.to_string())
}
}
impl From<$ty> for String {
fn from(t: $ty) -> Self {
t.0
}
}
impl From<&$ty> for String {
fn from(t: &$ty) -> Self {
t.0.clone()
}
}
impl AsRef<str> for $ty {
fn as_ref(&self) -> &str {
&self.0
}
}
impl std::ops::Deref for $ty {
type Target = str;
fn deref(&self) -> &str {
&self.0
}
}
impl fmt::Display for $ty {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl fmt::Debug for $ty {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
impl std::borrow::Borrow<str> for $ty {
fn borrow(&self) -> &str {
&self.0
}
}
impl PartialEq<str> for $ty {
fn eq(&self, other: &str) -> bool {
self.0 == other
}
}
impl PartialEq<&str> for $ty {
fn eq(&self, other: &&str) -> bool {
&self.0 == *other
}
}
impl PartialEq<String> for $ty {
fn eq(&self, other: &String) -> bool {
&self.0 == other
}
}
};
}
impl_name_newtype!(TableName);
impl_name_newtype!(ColumnName);
impl_name_newtype!(IndexName);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn table_name_new_constructs_from_str_literal() {
let name = TableName::new("user");
assert_eq!(name.as_str(), "user");
}
#[test]
fn column_name_new_constructs_from_owned_string() {
let name = ColumnName::new(String::from("email"));
assert_eq!(name.as_str(), "email");
}
#[test]
fn index_name_new_constructs_from_str_ref() {
let owned = "ix_user__email".to_string();
let name = IndexName::new(&*owned);
assert_eq!(name.as_str(), "ix_user__email");
}
#[test]
fn table_name_into_string_via_from() {
let name = TableName::new("orders");
let s: String = String::from(name);
assert_eq!(s, "orders");
}
#[test]
fn column_name_into_string_via_from() {
let name = ColumnName::new("created_at");
let s: String = String::from(name);
assert_eq!(s, "created_at");
}
#[test]
fn index_name_into_string_via_from() {
let name = IndexName::new("ix_orders__id");
let s: String = String::from(name);
assert_eq!(s, "ix_orders__id");
}
}