1use std::{
5 fmt,
6 hash::{BuildHasher, BuildHasherDefault, Hash},
7 mem::{self, ManuallyDrop},
8 ptr::NonNull,
9 sync::OnceLock,
10};
11
12use dashmap::{DashMap, SharedValue};
13use hashbrown::raw::RawTable;
14use rustc_hash::FxHasher;
15use triomphe::Arc;
16
17pub mod symbols;
18
19const _: () = assert!(size_of::<Box<str>>() == size_of::<&str>());
21const _: () = assert!(align_of::<Box<str>>() == align_of::<&str>());
22
23const _: () = assert!(size_of::<Arc<Box<str>>>() == size_of::<&&str>());
24const _: () = assert!(align_of::<Arc<Box<str>>>() == align_of::<&&str>());
25
26const _: () = assert!(size_of::<*const *const str>() == size_of::<TaggedArcPtr>());
27const _: () = assert!(align_of::<*const *const str>() == align_of::<TaggedArcPtr>());
28
29const _: () = assert!(size_of::<Arc<Box<str>>>() == size_of::<TaggedArcPtr>());
30const _: () = assert!(align_of::<Arc<Box<str>>>() == align_of::<TaggedArcPtr>());
31
32#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
37struct TaggedArcPtr {
38 packed: NonNull<*const str>,
39}
40
41unsafe impl Send for TaggedArcPtr {}
42unsafe impl Sync for TaggedArcPtr {}
43
44impl TaggedArcPtr {
45 const BOOL_BITS: usize = true as usize;
46
47 const fn non_arc(r: &'static &'static str) -> Self {
48 assert!(align_of::<&'static &'static str>().trailing_zeros() as usize > Self::BOOL_BITS);
49 let packed =
56 unsafe { NonNull::new_unchecked((r as *const &str).cast::<*const str>().cast_mut()) };
57 Self { packed }
58 }
59
60 fn arc(arc: Arc<Box<str>>) -> Self {
61 assert!(align_of::<&'static &'static str>().trailing_zeros() as usize > Self::BOOL_BITS);
62 Self {
63 packed: Self::pack_arc(
64 unsafe { NonNull::new_unchecked(Arc::into_raw(arc).cast_mut().cast()) },
66 ),
67 }
68 }
69
70 #[inline]
76 pub(crate) unsafe fn try_as_arc_owned(self) -> Option<ManuallyDrop<Arc<Box<str>>>> {
77 let tag = self.packed.as_ptr().addr() & Self::BOOL_BITS;
79 if tag != 0 {
80 Some(ManuallyDrop::new(unsafe {
82 Arc::from_raw(self.pointer().as_ptr().cast::<Box<str>>())
83 }))
84 } else {
85 None
86 }
87 }
88
89 #[inline]
90 fn pack_arc(ptr: NonNull<*const str>) -> NonNull<*const str> {
91 let packed_tag = true as usize;
92
93 unsafe {
94 NonNull::new_unchecked(ptr.as_ptr().map_addr(|addr| addr | packed_tag))
97 }
98 }
99
100 #[inline]
101 pub(crate) fn pointer(self) -> NonNull<*const str> {
102 unsafe {
104 NonNull::new_unchecked(self.packed.as_ptr().map_addr(|addr| addr & !Self::BOOL_BITS))
105 }
106 }
107
108 #[inline]
109 pub(crate) fn as_str(&self) -> &str {
110 unsafe { *self.pointer().as_ptr().cast::<&str>() }
112 }
113}
114
115#[derive(PartialEq, Eq, Hash)]
116pub struct Symbol {
117 repr: TaggedArcPtr,
118}
119
120impl fmt::Debug for Symbol {
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 self.as_str().fmt(f)
123 }
124}
125
126const _: () = assert!(size_of::<Symbol>() == size_of::<NonNull<()>>());
127const _: () = assert!(align_of::<Symbol>() == align_of::<NonNull<()>>());
128
129type Map = DashMap<Symbol, (), BuildHasherDefault<FxHasher>>;
130static MAP: OnceLock<Map> = OnceLock::new();
131
132impl Symbol {
133 pub fn intern(s: &str) -> Self {
134 let storage = MAP.get_or_init(symbols::prefill);
135 let (mut shard, hash) = Self::select_shard(storage, s);
136 let bucket = match shard.find_or_find_insert_slot(
143 hash,
144 |(other, _)| other.as_str() == s,
145 |(x, _)| Self::hash(storage, x.as_str()),
146 ) {
147 Ok(bucket) => bucket,
148 Err(insert_slot) => unsafe {
150 shard.insert_in_slot(
151 hash,
152 insert_slot,
153 (
154 Symbol { repr: TaggedArcPtr::arc(Arc::new(Box::<str>::from(s))) },
155 SharedValue::new(()),
156 ),
157 )
158 },
159 };
160 unsafe { bucket.as_ref().0.clone() }
162 }
163
164 pub fn integer(i: usize) -> Self {
165 match i {
166 0 => symbols::INTEGER_0,
167 1 => symbols::INTEGER_1,
168 2 => symbols::INTEGER_2,
169 3 => symbols::INTEGER_3,
170 4 => symbols::INTEGER_4,
171 5 => symbols::INTEGER_5,
172 6 => symbols::INTEGER_6,
173 7 => symbols::INTEGER_7,
174 8 => symbols::INTEGER_8,
175 9 => symbols::INTEGER_9,
176 10 => symbols::INTEGER_10,
177 11 => symbols::INTEGER_11,
178 12 => symbols::INTEGER_12,
179 13 => symbols::INTEGER_13,
180 14 => symbols::INTEGER_14,
181 15 => symbols::INTEGER_15,
182 i => Symbol::intern(&format!("{i}")),
183 }
184 }
185
186 pub fn empty() -> Self {
187 symbols::__empty
188 }
189
190 #[inline]
191 pub fn as_str(&self) -> &str {
192 self.repr.as_str()
193 }
194
195 #[inline]
196 fn select_shard(
197 storage: &'static Map,
198 s: &str,
199 ) -> (dashmap::RwLockWriteGuard<'static, RawTable<(Symbol, SharedValue<()>)>>, u64) {
200 let hash = Self::hash(storage, s);
201 let shard_idx = storage.determine_shard(hash as usize);
202 let shard = &storage.shards()[shard_idx];
203 (shard.write(), hash)
204 }
205
206 #[inline]
207 fn hash(storage: &'static Map, s: &str) -> u64 {
208 storage.hasher().hash_one(s)
209 }
210
211 #[cold]
212 fn drop_slow(arc: &Arc<Box<str>>) {
213 let storage = MAP.get_or_init(symbols::prefill);
214 let (mut shard, hash) = Self::select_shard(storage, arc);
215
216 match Arc::count(arc) {
217 0 | 1 => unreachable!(),
218 2 => (),
219 _ => {
220 return;
222 }
223 }
224
225 let s = &***arc;
226 let (ptr, _) = shard.remove_entry(hash, |(x, _)| x.as_str() == s).unwrap();
227 let ptr = ManuallyDrop::new(ptr);
228 ManuallyDrop::into_inner(unsafe { ptr.repr.try_as_arc_owned().unwrap() });
230 debug_assert_eq!(Arc::count(arc), 1);
231
232 if shard.len() * 2 < shard.capacity() {
234 let len = shard.len();
235 shard.shrink_to(len, |(x, _)| Self::hash(storage, x.as_str()));
236 }
237 }
238}
239
240impl Drop for Symbol {
241 #[inline]
242 fn drop(&mut self) {
243 let Some(arc) = (unsafe { self.repr.try_as_arc_owned() }) else {
245 return;
246 };
247 if Arc::count(&arc) == 2 {
249 Self::drop_slow(&arc);
252 }
253 ManuallyDrop::into_inner(arc);
255 }
256}
257
258impl Clone for Symbol {
259 fn clone(&self) -> Self {
260 Self { repr: increase_arc_refcount(self.repr) }
261 }
262}
263
264fn increase_arc_refcount(repr: TaggedArcPtr) -> TaggedArcPtr {
265 let Some(arc) = (unsafe { repr.try_as_arc_owned() }) else {
267 return repr;
268 };
269 mem::forget(Arc::clone(&arc));
271 repr
272}
273
274impl fmt::Display for Symbol {
275 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276 self.as_str().fmt(f)
277 }
278}
279
280#[cfg(test)]
281mod tests {
282 use super::*;
283
284 #[test]
285 fn smoke_test() {
286 Symbol::intern("isize");
287 let base_len = MAP.get().unwrap().len();
288 let hello = Symbol::intern("hello");
289 let world = Symbol::intern("world");
290 let more_worlds = world.clone();
291 let bang = Symbol::intern("!");
292 let q = Symbol::intern("?");
293 assert_eq!(MAP.get().unwrap().len(), base_len + 4);
294 let bang2 = Symbol::intern("!");
295 assert_eq!(MAP.get().unwrap().len(), base_len + 4);
296 drop(bang2);
297 assert_eq!(MAP.get().unwrap().len(), base_len + 4);
298 drop(q);
299 assert_eq!(MAP.get().unwrap().len(), base_len + 3);
300 let default = Symbol::intern("default");
301 let many_worlds = world.clone();
302 assert_eq!(MAP.get().unwrap().len(), base_len + 3);
303 assert_eq!(
304 "hello default world!",
305 format!("{} {} {}{}", hello.as_str(), default.as_str(), world.as_str(), bang.as_str())
306 );
307 drop(default);
308 assert_eq!(
309 "hello world!",
310 format!("{} {}{}", hello.as_str(), world.as_str(), bang.as_str())
311 );
312 drop(many_worlds);
313 drop(more_worlds);
314 drop(hello);
315 drop(world);
316 drop(bang);
317 assert_eq!(MAP.get().unwrap().len(), base_len);
318 }
319}