use std::borrow::{Borrow, Cow};
use std::hash::{Hash, Hasher};
use std::sync::Arc;
pub trait SqlSafeStr {
fn into_sql_str(self) -> SqlStr;
}
impl SqlSafeStr for &'static str {
#[inline]
fn into_sql_str(self) -> SqlStr {
SqlStr(Repr::Static(self))
}
}
pub struct AssertSqlSafe<T>(pub T);
impl SqlSafeStr for AssertSqlSafe<&str> {
#[inline]
fn into_sql_str(self) -> SqlStr {
SqlStr(Repr::Arced(self.0.into()))
}
}
impl SqlSafeStr for AssertSqlSafe<String> {
#[inline]
fn into_sql_str(self) -> SqlStr {
SqlStr(Repr::Owned(self.0))
}
}
impl SqlSafeStr for AssertSqlSafe<Box<str>> {
#[inline]
fn into_sql_str(self) -> SqlStr {
SqlStr(Repr::Boxed(self.0))
}
}
impl SqlSafeStr for AssertSqlSafe<Arc<str>> {
#[inline]
fn into_sql_str(self) -> SqlStr {
SqlStr(Repr::Arced(self.0))
}
}
impl SqlSafeStr for AssertSqlSafe<Arc<String>> {
#[inline]
fn into_sql_str(self) -> SqlStr {
SqlStr(Repr::ArcString(self.0))
}
}
impl SqlSafeStr for AssertSqlSafe<Cow<'static, str>> {
fn into_sql_str(self) -> SqlStr {
match self.0 {
Cow::Borrowed(str) => str.into_sql_str(),
Cow::Owned(str) => AssertSqlSafe(str).into_sql_str(),
}
}
}
#[derive(Debug)]
pub struct SqlStr(Repr);
#[derive(Debug)]
enum Repr {
Static(&'static str),
Owned(String),
Boxed(Box<str>),
Arced(Arc<str>),
ArcString(Arc<String>),
}
impl Clone for SqlStr {
fn clone(&self) -> Self {
Self(match &self.0 {
Repr::Static(s) => Repr::Static(s),
Repr::Arced(s) => Repr::Arced(s.clone()),
_ => Repr::Arced(self.as_str().into()),
})
}
}
impl SqlSafeStr for SqlStr {
#[inline]
fn into_sql_str(self) -> SqlStr {
self
}
}
impl SqlStr {
#[inline]
pub fn as_str(&self) -> &str {
match &self.0 {
Repr::Static(s) => s,
Repr::Owned(s) => s,
Repr::Boxed(s) => s,
Repr::Arced(s) => s,
Repr::ArcString(s) => s,
}
}
pub const fn from_static(sql: &'static str) -> Self {
SqlStr(Repr::Static(sql))
}
}
impl AsRef<str> for SqlStr {
#[inline]
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl Borrow<str> for SqlStr {
#[inline]
fn borrow(&self) -> &str {
self.as_str()
}
}
impl<T> PartialEq<T> for SqlStr
where
T: AsRef<str>,
{
fn eq(&self, other: &T) -> bool {
self.as_str() == other.as_ref()
}
}
impl Eq for SqlStr {}
impl Hash for SqlStr {
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_str().hash(state)
}
}