use crate::*;
use std::str::FromStr;
#[cfg(feature = "global")]
#[macro_export]
macro_rules! static_symbol {
($s:literal) => {{
use std::sync::OnceLock;
static SYMBOL: OnceLock<$crate::GlobalSymbol> = OnceLock::new();
*SYMBOL.get_or_init(|| $crate::GlobalSymbol::from($s))
}};
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(into = "&'static str"))]
pub struct GlobalSymbol(Symbol);
impl From<NonZeroU32> for GlobalSymbol {
fn from(n: NonZeroU32) -> Self {
Self(Symbol::from(n))
}
}
impl From<GlobalSymbol> for NonZeroU32 {
fn from(n: GlobalSymbol) -> Self {
n.0.into()
}
}
static SINGLETON: SymbolTable = SymbolTable::new();
impl GlobalSymbol {
pub fn new(s: impl AsRef<str>) -> Self {
s.as_ref().into()
}
pub fn as_str(&self) -> &'static str {
(*self).into()
}
}
impl From<&str> for GlobalSymbol {
fn from(s: &str) -> Self {
GlobalSymbol(SINGLETON.intern(s))
}
}
impl From<String> for GlobalSymbol {
fn from(s: String) -> Self {
s.as_str().into()
}
}
impl From<&String> for GlobalSymbol {
fn from(s: &String) -> Self {
s.as_str().into()
}
}
impl FromStr for GlobalSymbol {
type Err = std::convert::Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(s.into())
}
}
impl From<GlobalSymbol> for &'static str {
fn from(sym: GlobalSymbol) -> Self {
SINGLETON.resolve(sym.0)
}
}
impl std::fmt::Debug for GlobalSymbol {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(self.as_str(), f)
}
}
impl std::fmt::Display for GlobalSymbol {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.as_str(), f)
}
}
#[cfg(feature = "serde")]
struct StrVisitor;
#[cfg(feature = "serde")]
impl serde::de::Visitor<'_> for StrVisitor {
type Value = GlobalSymbol;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a &str")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(v.into())
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for GlobalSymbol {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_str(StrVisitor)
}
}