1use std::borrow::Borrow;
2use std::hash::{Hash, Hasher};
3use std::num::NonZeroUsize;
4use std::ops::Deref;
5use std::sync::{Arc, Weak};
6use std::{cmp, fmt};
7
8use trait_set::trait_set;
9
10#[allow(unused)] use super::interner::Interner;
12use super::typed_interner::TypedInterner;
13use crate::global::{self, ev};
14
15trait_set! {
16 pub trait Internable = Eq + Hash + Clone + Send + Sync + 'static;
17}
18
19#[derive(Clone)]
31pub struct Tok<T: Internable> {
32 data: Arc<T>,
33 interner: Arc<TypedInterner<T>>,
34}
35impl<T: Internable> Tok<T> {
36 #[must_use]
38 pub(crate) fn new(data: Arc<T>, interner: Arc<TypedInterner<T>>) -> Self {
39 Self { data, interner }
40 }
41 #[must_use]
44 pub fn id(&self) -> NonZeroUsize {
45 ((self.data.as_ref() as *const T as usize).try_into())
46 .expect("Pointer can always be cast to nonzero")
47 }
48 pub fn interner_id(&self) -> NonZeroUsize {
51 ((self.interner.as_ref() as *const _ as usize).try_into())
52 .expect("Pointer can always be cast to nonzero")
53 }
54 #[must_use]
56 pub fn usize(&self) -> usize { self.id().into() }
57 pub fn assert_comparable(&self, other: &Self) {
59 assert_eq!(self.interner_id(), other.interner_id(), "Tokens must come from the same interner");
60 }
61 pub fn interner(&self) -> Arc<TypedInterner<T>> { self.interner.clone() }
63
64 pub fn i<Q>(q: &Q) -> Self
65 where
66 Q: ?Sized + Eq + Hash + ToOwned<Owned = T>,
67 T: Borrow<Q>,
68 {
69 global::i(q)
70 }
71}
72
73impl<T: Internable> Tok<Vec<Tok<T>>> {
74 pub fn ev(&self) -> Vec<T> { ev(&self[..]) }
77}
78
79impl<T: Internable> Tok<Vec<Tok<T>>> {
80 pub fn append(&self, suffix: impl IntoIterator<Item = Tok<T>>) -> Self {
82 let i = self.interner();
83 i.i(&self.iter().cloned().chain(suffix).collect::<Vec<_>>())
84 }
85
86 pub fn prepend(&self, prefix: impl IntoIterator<Item = Tok<T>>) -> Self {
88 let i = self.interner();
89 i.i(&prefix.into_iter().chain(self.iter().cloned()).collect::<Vec<_>>())
90 }
91}
92
93impl<T: Internable + AsRef<U>, U: ?Sized> AsRef<U> for Tok<T> {
94 fn as_ref(&self) -> &U { self.data.as_ref().as_ref() }
95}
96
97impl<T: Internable> Borrow<T> for Tok<T> {
98 fn borrow(&self) -> &T { self.data.as_ref().borrow() }
99}
100
101impl<T: Internable> Deref for Tok<T> {
102 type Target = T;
103
104 fn deref(&self) -> &Self::Target { self.data.as_ref() }
105}
106
107impl<T: Internable + fmt::Debug> fmt::Debug for Tok<T> {
108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 write!(f, "Token({} -> {:?})", self.id(), self.data.as_ref())
110 }
111}
112
113impl<T: Internable + fmt::Display> fmt::Display for Tok<T> {
114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", **self) }
115}
116
117impl<T: Internable> Eq for Tok<T> {}
118impl<T: Internable> cmp::PartialEq for Tok<T> {
119 fn eq(&self, other: &Self) -> bool {
120 self.assert_comparable(other);
121 self.id() == other.id()
122 }
123}
124
125impl<T: Internable> cmp::Ord for Tok<T> {
126 fn cmp(&self, other: &Self) -> cmp::Ordering {
127 self.assert_comparable(other);
128 self.id().cmp(&other.id())
129 }
130}
131impl<T: Internable> cmp::PartialOrd for Tok<T> {
132 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { Some(self.cmp(other)) }
133}
134
135impl<T: Internable> Hash for Tok<T> {
136 fn hash<H: Hasher>(&self, state: &mut H) { state.write_usize(self.usize()) }
137}
138
139pub struct WeakTok<T: Internable> {
140 data: Weak<T>,
141 interner: Weak<TypedInterner<T>>,
142}
143impl<T: Internable> WeakTok<T> {
144 pub fn new(tok: &Tok<T>) -> Self {
145 Self { data: Arc::downgrade(&tok.data), interner: Arc::downgrade(&tok.interner) }
146 }
147 pub fn upgrade(&self) -> Option<Tok<T>> {
148 Some(Tok { data: self.data.upgrade()?, interner: self.interner.upgrade()? })
149 }
150}
151
152#[cfg(feature = "serde")]
153impl<T: serde::Serialize + Internable> serde::Serialize for Tok<T> {
154 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
155 where
156 S: serde::Serializer,
157 {
158 self.data.serialize(serializer)
159 }
160}
161
162#[cfg(feature = "serde")]
163impl<'a, T: serde::Deserialize<'a> + Internable> serde::Deserialize<'a> for Tok<T> {
164 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
165 where
166 D: serde::Deserializer<'a>,
167 {
168 T::deserialize(deserializer).map(|t| crate::i(&t))
169 }
170}
171
172#[cfg(test)]
173mod test {
174 use crate::{i, Tok};
175
176 #[test]
177 fn impls_asref() {
178 fn foo(_: impl AsRef<str>) {}
179 let t: Tok<String> = i("Hello World!");
180 foo(t)
181 }
182}