use std::fmt;
use std::sync::Arc;
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Name(ustr::Ustr);
impl Name {
#[inline]
pub fn new(s: &str) -> Self {
Self(ustr::ustr(s))
}
#[inline]
pub fn as_str(&self) -> &str {
self.0.as_str()
}
pub fn ascii_lowercase(self) -> Self {
if self.as_str().bytes().all(|b| !b.is_ascii_uppercase()) {
return self;
}
static CACHE: std::sync::OnceLock<dashmap::DashMap<ustr::Ustr, ustr::Ustr>> =
std::sync::OnceLock::new();
let cache = CACHE.get_or_init(dashmap::DashMap::default);
if let Some(v) = cache.get(&self.0) {
return Name(*v);
}
let lowered = ustr::ustr(&self.as_str().to_ascii_lowercase());
cache.insert(self.0, lowered);
Name(lowered)
}
}
impl From<&str> for Name {
#[inline]
fn from(s: &str) -> Self {
Self::new(s)
}
}
impl From<String> for Name {
#[inline]
fn from(s: String) -> Self {
Self::new(&s)
}
}
impl From<Arc<str>> for Name {
#[inline]
fn from(s: Arc<str>) -> Self {
Self::new(&s)
}
}
impl From<Name> for String {
#[inline]
fn from(s: Name) -> String {
s.as_str().to_string()
}
}
impl From<Name> for Arc<str> {
#[inline]
fn from(s: Name) -> Arc<str> {
Arc::from(s.as_str())
}
}
impl std::ops::Deref for Name {
type Target = str;
#[inline]
fn deref(&self) -> &str {
self.as_str()
}
}
impl AsRef<str> for Name {
#[inline]
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl PartialEq<str> for Name {
#[inline]
fn eq(&self, other: &str) -> bool {
self.as_str() == other
}
}
impl PartialEq<Name> for str {
#[inline]
fn eq(&self, other: &Name) -> bool {
self == other.as_str()
}
}
impl PartialEq<String> for Name {
#[inline]
fn eq(&self, other: &String) -> bool {
self.as_str() == other.as_str()
}
}
impl PartialEq<Arc<str>> for Name {
#[inline]
fn eq(&self, other: &Arc<str>) -> bool {
self.as_str() == other.as_ref()
}
}
impl PartialEq<Name> for Arc<str> {
#[inline]
fn eq(&self, other: &Name) -> bool {
self.as_ref() == other.as_str()
}
}
impl fmt::Display for Name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl fmt::Debug for Name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Name({:?})", self.as_str())
}
}
impl Serialize for Name {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(self.as_str())
}
}
impl<'de> Deserialize<'de> for Name {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let s = std::borrow::Cow::<str>::deserialize(deserializer)?;
Ok(Self::new(&s))
}
}