1use std::any::{Any, TypeId};
2use std::borrow::Borrow;
3use std::hash::Hash;
4use std::ops::DerefMut;
5use std::sync::{Arc, Mutex};
6
7use hashbrown::HashMap;
8
9use super::token::Tok;
10use super::typed_interner::TypedInterner;
11use crate::token::Internable;
12
13pub trait AnyInterner: Send + Sync {
16 fn as_any_arc(self: Arc<Self>) -> Arc<dyn Any + Send + Sync>;
17 fn sweep(&self) -> usize;
18}
19
20impl<T: Internable> AnyInterner for TypedInterner<T> {
21 fn as_any_arc(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> { self }
22 fn sweep(&self) -> usize { TypedInterner::sweep(self) }
23}
24
25pub struct Interner {
29 interners: Mutex<HashMap<TypeId, Arc<dyn AnyInterner>>>,
30}
31impl Interner {
32 #[must_use]
34 pub fn new() -> Self { Self { interners: Mutex::new(HashMap::new()) } }
35
36 #[must_use]
38 pub fn i<Q>(&self, q: &Q) -> Tok<Q::Owned>
39 where
40 Q: ?Sized + Eq + Hash + ToOwned,
41 Q::Owned: Internable + Borrow<Q>,
42 {
43 let mut interners = self.interners.lock().unwrap();
44 let interner = get_interner(&mut interners);
45 interner.i(q)
46 }
47
48 pub fn sweep_t<T: Internable>(&self) -> usize {
52 match self.interners.lock().unwrap().get(&TypeId::of::<T>()) {
53 None => 0,
54 Some(interner) => interner.sweep(),
55 }
56 }
57
58 pub fn sweep(&self) -> usize { self.interners.lock().unwrap().values().map(|v| v.sweep()).sum() }
60
61 pub fn iv<T: Internable>(&self, s: impl IntoIterator<Item = T>) -> Tok<Vec<Tok<T>>> {
63 self.i(&s.into_iter().map(|t| self.i(&t)).collect::<Vec<_>>())
64 }
65
66 pub fn ibv<'a, Q>(&self, s: impl IntoIterator<Item = &'a Q>) -> Tok<Vec<Tok<Q::Owned>>>
68 where
69 Q: ?Sized + Eq + Hash + ToOwned + 'a,
70 Q::Owned: Internable,
71 {
72 self.i(&s.into_iter().map(|t| self.i(t)).collect::<Vec<_>>())
73 }
74}
75
76impl Default for Interner {
77 fn default() -> Self { Self::new() }
78}
79
80#[must_use]
82fn get_interner<T: Internable>(
83 interners: &mut impl DerefMut<Target = HashMap<TypeId, Arc<dyn AnyInterner>>>,
84) -> Arc<TypedInterner<T>> {
85 let boxed = interners
86 .raw_entry_mut()
87 .from_key(&TypeId::of::<T>())
88 .or_insert_with(|| (TypeId::of::<T>(), TypedInterner::<T>::new()))
89 .1
90 .clone();
91 (Arc::downcast(boxed.as_any_arc())).expect("the typeid is supposed to protect from this")
92}
93
94#[cfg(test)]
95mod test {
96 use super::*;
97
98 #[test]
99 pub fn test_string() {
100 let interner = Interner::new();
101 let key1 = interner.i("foo");
102 let key2 = interner.i(&"foo".to_string());
103 assert_eq!(key1, key2)
104 }
105
106 #[test]
107 pub fn test_slice() {
108 let interner = Interner::new();
109 let key1 = interner.i(&vec![1, 2, 3]);
110 let key2 = interner.i(&[1, 2, 3][..]);
111 assert_eq!(key1, key2);
112 }
113
114 #[test]
115 pub fn test_str_slice() {
116 let interner = Interner::new();
117 let key1 = interner.iv(["a".to_string(), "b".to_string(), "c".to_string()]);
118 let key2 = interner.ibv(vec!["a", "b", "c"]);
119 assert_eq!(key1, key2);
120 }
121}