1 use hashbrown::{hash_map::RawEntryMut, HashMap};
13 pub struct Interned<T: ?Sized> {
17 impl<T: ?Sized> Deref for Interned<T> {
20 fn deref(&self) -> &Self::Target {
25 impl<T: ?Sized> Hash for Interned<T> {
26 fn hash<H: Hasher>(&self, state: &mut H) {
27 Rc::as_ptr(&self.ptr).hash(state);
31 impl<T: ?Sized> Eq for Interned<T> {}
33 impl<T: ?Sized + fmt::Debug> fmt::Debug for Interned<T> {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 impl<T: ?Sized + fmt::Display> fmt::Display for Interned<T> {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 impl<T: ?Sized + Serialize> Serialize for Interned<T> {
46 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
50 self.ptr.serialize(serializer)
54 impl<T: ?Sized> PartialEq for Interned<T> {
55 fn eq(&self, other: &Interned<T>) -> bool {
56 Rc::ptr_eq(&self.ptr, &other.ptr)
60 impl<T: ?Sized> PartialOrd for Interned<T> {
61 fn partial_cmp(&self, other: &Interned<T>) -> Option<Ordering> {
66 impl<T: ?Sized> Ord for Interned<T> {
67 fn cmp(&self, other: &Interned<T>) -> Ordering {
68 Rc::as_ptr(&self.ptr).cmp(&Rc::as_ptr(&other.ptr))
77 pub struct GlobalArena {
81 scoped_tls::scoped_thread_local!(static GLOBAL_ARENA: GlobalArena);
84 pub fn scope<R>(f: impl FnOnce() -> R) -> R {
87 interners: Interners::default(),
92 pub fn get<R>(f: impl for<'a> FnOnce(&'a GlobalArena) -> R) -> R {
97 pub struct Interner<T: ?Sized>(RefCell<HashMap<Rc<T>, ()>>);
99 impl<T: ?Sized> Default for Interner<T> {
100 fn default() -> Self {
101 Self(Default::default())
105 pub struct InternInput<
107 T: ?Sized + Eq + Hash,
108 B: FnOnce(&Input) -> &T,
109 R: FnOnce(Input) -> Rc<T>,
116 impl<T: ?Sized + Eq + Hash> Interner<T> {
119 v: InternInput<Input, T, impl FnOnce(&Input) -> &T, impl FnOnce(Input) -> Rc<T>>,
126 match self.0.borrow_mut().raw_entry_mut().from_key(borrow(&input)) {
127 RawEntryMut::Occupied(entry) => Interned {
128 ptr: entry.key().clone(),
130 RawEntryMut::Vacant(entry) => Interned {
131 ptr: entry.insert(into_rc(input), ()).0.clone(),
137 pub trait InternTarget: Intern<Target = Self> + Hash + Eq {
138 fn get_interner(global_arena: &GlobalArena) -> &Interner<Self>;
139 fn into_interned(input: Self, global_arena: &GlobalArena) -> Interned<Self>
143 Self::get_interner(global_arena).intern(InternInput {
149 fn rc_into_interned(input: Rc<Self>, global_arena: &GlobalArena) -> Interned<Self> {
150 Self::get_interner(global_arena).intern(InternInput {
156 fn rc_to_interned(input: &Rc<Self>, global_arena: &GlobalArena) -> Interned<Self> {
157 Self::get_interner(global_arena).intern(InternInput {
160 into_rc: |v| v.clone(),
165 impl InternTarget for str {
166 fn get_interner(global_arena: &GlobalArena) -> &Interner<Self> {
167 &global_arena.interners.str
171 impl Intern for str {
174 fn to_rc_target(v: &Self) -> Rc<Self::Target> {
178 fn to_interned(&self, global_arena: &GlobalArena) -> Interned<Self::Target> {
179 Self::get_interner(global_arena).intern(InternInput {
182 into_rc: Self::to_rc_target,
187 impl Intern for &'_ str {
190 fn to_rc_target(v: &Self) -> Rc<Self::Target> {
194 fn to_interned(&self, global_arena: &GlobalArena) -> Interned<Self::Target> {
195 Self::Target::to_interned(self, global_arena)
198 fn into_interned(self, global_arena: &GlobalArena) -> Interned<Self::Target>
202 Self::Target::to_interned(self, global_arena)
206 impl Intern for &'_ mut str {
209 fn to_rc_target(v: &Self) -> Rc<Self::Target> {
213 fn to_interned(&self, global_arena: &GlobalArena) -> Interned<Self::Target> {
214 Self::Target::to_interned(self, global_arena)
217 fn into_interned(self, global_arena: &GlobalArena) -> Interned<Self::Target>
221 Self::Target::to_interned(self, global_arena)
225 impl Intern for String {
228 fn to_rc_target(v: &Self) -> Rc<Self::Target> {
232 fn to_interned(&self, global_arena: &GlobalArena) -> Interned<Self::Target> {
233 Self::Target::to_interned(self, global_arena)
236 fn into_rc_target(v: Self) -> Rc<Self::Target>
243 fn into_interned(self, global_arena: &GlobalArena) -> Interned<Self::Target>
247 Self::Target::to_interned(&self, global_arena)
252 type Target: ?Sized + InternTarget;
253 fn into_rc_target(v: Self) -> Rc<Self::Target>
257 Self::to_rc_target(&v)
259 fn to_rc_target(v: &Self) -> Rc<Self::Target>;
260 fn into_interned(self, global_arena: &GlobalArena) -> Interned<Self::Target>
264 <<Self as Intern>::Target as InternTarget>::rc_into_interned(
265 Self::into_rc_target(self),
269 fn to_interned(&self, global_arena: &GlobalArena) -> Interned<Self::Target> {
270 Self::Target::rc_into_interned(Self::to_rc_target(self), global_arena)
274 impl<T: ?Sized + InternTarget> Intern for Rc<T> {
277 fn to_rc_target(v: &Self) -> Rc<Self::Target> {
281 fn into_rc_target(v: Self) -> Rc<Self::Target>
289 impl<T: Clone + InternTarget> Intern for T {
292 fn to_rc_target(v: &Self) -> Rc<Self::Target> {
296 fn into_rc_target(v: Self) -> Rc<Self::Target>
303 fn into_interned(self, global_arena: &GlobalArena) -> Interned<Self::Target>
307 InternTarget::into_interned(self, global_arena)
310 fn to_interned(&self, global_arena: &GlobalArena) -> Interned<Self::Target> {
311 InternTarget::get_interner(global_arena).intern(InternInput {
314 into_rc: |v| v.clone().into(),