intern_all/
token.rs

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)] // for doc
11use 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/// A shared instance. Equality comparison costs two pointer comparisons.
20/// Ordering is by pointer value.
21///
22/// # Panics
23///
24/// If an interner was manually constructed, tokens from different interners
25/// cannot be compared and attempting to do so causes a panic.
26///
27/// Since a given [Interner] uses a single [TypedInterner] for each type, this
28/// is only possible if an [Interner] or [TypedInterner] was constructed besides
29/// the singleton.
30#[derive(Clone)]
31pub struct Tok<T: Internable> {
32  data: Arc<T>,
33  interner: Arc<TypedInterner<T>>,
34}
35impl<T: Internable> Tok<T> {
36  /// Create a new token. Used exclusively by the interner
37  #[must_use]
38  pub(crate) fn new(data: Arc<T>, interner: Arc<TypedInterner<T>>) -> Self {
39    Self { data, interner }
40  }
41  /// The pointer value of the token. If this is equal, equality comparison
42  /// succeeds.
43  #[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  /// The pointer value of the interner. If this is different, comparison
49  /// panics.
50  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  /// Cast into usize
55  #[must_use]
56  pub fn usize(&self) -> usize { self.id().into() }
57  /// Panic if the two tokens weren't created with the same interner
58  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  /// Get the typed interner that owns this token.
62  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  /// Extern all elements of the vector in a new vector. If the vector itself
75  /// isn't interned, use [ev]
76  pub fn ev(&self) -> Vec<T> { ev(&self[..]) }
77}
78
79impl<T: Internable> Tok<Vec<Tok<T>>> {
80  /// Add a suffix to the interned vector
81  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  /// Add a prefix to the interned vector
87  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}