yazi_shared/pool/
symbol.rs1use std::{borrow::Cow, hash::{Hash, Hasher}, marker::PhantomData, mem::ManuallyDrop, ops::Deref, str};
2
3use hashbrown::hash_map::RawEntryMut;
4use serde::Deserialize;
5
6use crate::pool::{Pool, SYMBOLS, SymbolPtr, compute_hash};
7
8pub struct Symbol<T: ?Sized> {
9 ptr: SymbolPtr,
10 _phantom: PhantomData<T>,
11}
12
13unsafe impl<T: ?Sized> Send for Symbol<T> {}
14
15unsafe impl<T: ?Sized> Sync for Symbol<T> {}
16
17impl<T: ?Sized> Clone for Symbol<T> {
18 fn clone(&self) -> Self {
19 let hash = compute_hash(&self.ptr);
20 match SYMBOLS.lock().raw_entry_mut().from_key_hashed_nocheck(hash, &self.ptr) {
21 RawEntryMut::Occupied(mut oe) => *oe.get_mut() += 1,
22 RawEntryMut::Vacant(_) => unreachable!(),
23 }
24 Self::new(self.ptr.clone())
25 }
26}
27
28impl<T: ?Sized> Drop for Symbol<T> {
29 fn drop(&mut self) {
30 let hash = compute_hash(&self.ptr);
31 match SYMBOLS.lock().raw_entry_mut().from_key_hashed_nocheck(hash, &self.ptr) {
32 RawEntryMut::Occupied(mut oe) => {
33 let count = oe.get_mut();
34 *count -= 1;
35
36 if *count == 0 {
37 oe.remove();
38 drop(unsafe { Box::from_raw(self.ptr.as_ptr()) });
39 }
40 }
41 RawEntryMut::Vacant(_) => unreachable!(),
42 }
43 }
44}
45
46impl AsRef<[u8]> for Symbol<[u8]> {
47 fn as_ref(&self) -> &[u8] { self.ptr.bytes() }
48}
49
50impl AsRef<str> for Symbol<str> {
51 fn as_ref(&self) -> &str { unsafe { str::from_utf8_unchecked(self.ptr.bytes()) } }
52}
53
54impl Deref for Symbol<[u8]> {
55 type Target = [u8];
56
57 fn deref(&self) -> &Self::Target { self.as_ref() }
58}
59
60impl Deref for Symbol<str> {
61 type Target = str;
62
63 fn deref(&self) -> &Self::Target { self.as_ref() }
64}
65
66impl Default for Symbol<[u8]> {
68 fn default() -> Self { Pool::<[u8]>::intern(b"") }
69}
70
71impl Default for Symbol<str> {
72 fn default() -> Self { Pool::<str>::intern("") }
73}
74
75impl<T: ?Sized> PartialEq for Symbol<T> {
77 fn eq(&self, other: &Self) -> bool { self.ptr == other.ptr }
78}
79
80impl<T: ?Sized> Eq for Symbol<T> {}
81
82impl PartialEq<str> for Symbol<str> {
83 fn eq(&self, other: &str) -> bool { self.as_ref() == other }
84}
85
86impl PartialEq<&str> for Symbol<str> {
87 fn eq(&self, other: &&str) -> bool { self.as_ref() == *other }
88}
89
90impl PartialEq<[u8]> for Symbol<[u8]> {
91 fn eq(&self, other: &[u8]) -> bool { self.as_ref() == other }
92}
93
94impl<T: ?Sized> Hash for Symbol<T> {
96 fn hash<H: Hasher>(&self, state: &mut H) { self.ptr.as_ptr().hash(state); }
97}
98
99impl Ord for Symbol<[u8]> {
101 fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.as_ref().cmp(other.as_ref()) }
102}
103
104impl Ord for Symbol<str> {
105 fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.as_ref().cmp(other.as_ref()) }
106}
107
108impl PartialOrd for Symbol<[u8]> {
110 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { Some(self.cmp(other)) }
111}
112
113impl PartialOrd for Symbol<str> {
114 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { Some(self.cmp(other)) }
115}
116
117impl std::fmt::Display for Symbol<str> {
119 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120 write!(f, "{}", self.as_ref())
121 }
122}
123
124impl std::fmt::Debug for Symbol<[u8]> {
126 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127 write!(f, "Symbol<[u8]>({:?})", self.as_ref())
128 }
129}
130
131impl std::fmt::Debug for Symbol<str> {
132 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133 write!(f, "Symbol<str>({:?})", self.as_ref())
134 }
135}
136
137impl<'de> Deserialize<'de> for Symbol<str> {
138 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
139 where
140 D: serde::Deserializer<'de>,
141 {
142 Cow::<str>::deserialize(deserializer).map(Pool::<str>::intern)
143 }
144}
145
146impl<T: ?Sized> Symbol<T> {
147 #[inline]
148 pub(super) fn new(ptr: SymbolPtr) -> Self { Self { ptr, _phantom: PhantomData } }
149
150 #[inline]
151 pub(super) fn into_ptr(self) -> SymbolPtr { ManuallyDrop::new(self).ptr.clone() }
152}