1use crate::*;
2
3use std::str::FromStr;
4
5#[cfg(feature = "global")]
6#[macro_export]
23macro_rules! static_symbol {
24 ($s:literal) => {{
25 use std::sync::OnceLock;
26 static SYMBOL: OnceLock<$crate::GlobalSymbol> = OnceLock::new();
27
28 *SYMBOL.get_or_init(|| $crate::GlobalSymbol::from($s))
29 }};
30}
31
32#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
45#[cfg_attr(feature = "serde", derive(serde::Serialize))]
46#[cfg_attr(feature = "serde", serde(into = "&'static str"))]
47pub struct GlobalSymbol(Symbol);
48
49impl From<NonZeroU32> for GlobalSymbol {
50 fn from(n: NonZeroU32) -> Self {
51 Self(Symbol::from(n))
52 }
53}
54
55impl From<GlobalSymbol> for NonZeroU32 {
56 fn from(n: GlobalSymbol) -> Self {
57 n.0.into()
58 }
59}
60
61static SINGLETON: SymbolTable = SymbolTable::new();
62
63impl GlobalSymbol {
64 pub fn new(s: impl AsRef<str>) -> Self {
66 s.as_ref().into()
67 }
68
69 pub fn as_str(&self) -> &'static str {
71 (*self).into()
72 }
73}
74
75impl From<&str> for GlobalSymbol {
76 fn from(s: &str) -> Self {
77 GlobalSymbol(SINGLETON.intern(s))
78 }
79}
80
81impl From<String> for GlobalSymbol {
82 fn from(s: String) -> Self {
83 s.as_str().into()
84 }
85}
86
87impl From<&String> for GlobalSymbol {
88 fn from(s: &String) -> Self {
89 s.as_str().into()
90 }
91}
92
93impl FromStr for GlobalSymbol {
94 type Err = std::convert::Infallible;
95
96 fn from_str(s: &str) -> Result<Self, Self::Err> {
97 Ok(s.into())
98 }
99}
100
101impl From<GlobalSymbol> for &'static str {
102 fn from(sym: GlobalSymbol) -> Self {
103 SINGLETON.resolve(sym.0)
104 }
105}
106
107impl std::fmt::Debug for GlobalSymbol {
108 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109 std::fmt::Debug::fmt(self.as_str(), f)
110 }
111}
112
113impl std::fmt::Display for GlobalSymbol {
114 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
115 std::fmt::Display::fmt(self.as_str(), f)
116 }
117}
118
119#[cfg(feature = "serde")]
120struct StrVisitor;
121
122#[cfg(feature = "serde")]
123impl serde::de::Visitor<'_> for StrVisitor {
124 type Value = GlobalSymbol;
125
126 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
127 formatter.write_str("a &str")
128 }
129
130 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
131 where
132 E: serde::de::Error,
133 {
134 Ok(v.into())
135 }
136}
137
138#[cfg(feature = "serde")]
139impl<'de> serde::Deserialize<'de> for GlobalSymbol {
140 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
141 where
142 D: serde::Deserializer<'de>,
143 {
144 deserializer.deserialize_str(StrVisitor)
145 }
146}