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