|
1 | 1 | use std::any::{Any, TypeId};
|
2 |
| -use std::borrow::Borrow; |
3 | 2 | use std::cell::RefCell;
|
4 |
| -use std::cmp::Ordering; |
5 | 3 | use std::collections::HashMap;
|
6 |
| -use std::fmt; |
7 |
| -use std::hash::{Hash, Hasher}; |
8 |
| -use std::marker::PhantomData; |
9 |
| -use std::mem; |
10 |
| -use std::ops::Deref; |
11 |
| -use std::path::PathBuf; |
12 |
| -use std::sync::{LazyLock, Mutex}; |
13 | 4 |
|
14 | 5 | use crate::core::builder::Step;
|
15 | 6 |
|
16 |
| -pub struct Interned<T>(usize, PhantomData<*const T>); |
17 |
| - |
18 |
| -impl<T: Internable + Default> Default for Interned<T> { |
19 |
| - fn default() -> Self { |
20 |
| - T::default().intern() |
21 |
| - } |
22 |
| -} |
23 |
| - |
24 |
| -impl<T> Copy for Interned<T> {} |
25 |
| -impl<T> Clone for Interned<T> { |
26 |
| - fn clone(&self) -> Interned<T> { |
27 |
| - *self |
28 |
| - } |
29 |
| -} |
30 |
| - |
31 |
| -impl<T> PartialEq for Interned<T> { |
32 |
| - fn eq(&self, other: &Self) -> bool { |
33 |
| - self.0 == other.0 |
34 |
| - } |
35 |
| -} |
36 |
| -impl<T> Eq for Interned<T> {} |
37 |
| - |
38 |
| -impl PartialEq<str> for Interned<String> { |
39 |
| - fn eq(&self, other: &str) -> bool { |
40 |
| - *self == other |
41 |
| - } |
42 |
| -} |
43 |
| -impl<'a> PartialEq<&'a str> for Interned<String> { |
44 |
| - fn eq(&self, other: &&str) -> bool { |
45 |
| - **self == **other |
46 |
| - } |
47 |
| -} |
48 |
| -impl<'a, T> PartialEq<&'a Interned<T>> for Interned<T> { |
49 |
| - fn eq(&self, other: &&Self) -> bool { |
50 |
| - self.0 == other.0 |
51 |
| - } |
52 |
| -} |
53 |
| -impl<'a, T> PartialEq<Interned<T>> for &'a Interned<T> { |
54 |
| - fn eq(&self, other: &Interned<T>) -> bool { |
55 |
| - self.0 == other.0 |
56 |
| - } |
57 |
| -} |
58 |
| - |
59 |
| -unsafe impl<T> Send for Interned<T> {} |
60 |
| -unsafe impl<T> Sync for Interned<T> {} |
61 |
| - |
62 |
| -impl fmt::Display for Interned<String> { |
63 |
| - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
64 |
| - let s: &str = self; |
65 |
| - f.write_str(s) |
66 |
| - } |
67 |
| -} |
68 |
| - |
69 |
| -impl<T, U: ?Sized + fmt::Debug> fmt::Debug for Interned<T> |
70 |
| -where |
71 |
| - Self: Deref<Target = U>, |
72 |
| -{ |
73 |
| - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
74 |
| - let s: &U = self; |
75 |
| - f.write_fmt(format_args!("{s:?}")) |
76 |
| - } |
77 |
| -} |
78 |
| - |
79 |
| -impl<T: Internable + Hash> Hash for Interned<T> { |
80 |
| - fn hash<H: Hasher>(&self, state: &mut H) { |
81 |
| - let l = T::intern_cache().lock().unwrap(); |
82 |
| - l.get(*self).hash(state) |
83 |
| - } |
84 |
| -} |
85 |
| - |
86 |
| -impl<T: Internable + Deref> Deref for Interned<T> { |
87 |
| - type Target = T::Target; |
88 |
| - fn deref(&self) -> &Self::Target { |
89 |
| - let l = T::intern_cache().lock().unwrap(); |
90 |
| - unsafe { mem::transmute::<&Self::Target, &Self::Target>(l.get(*self)) } |
91 |
| - } |
92 |
| -} |
93 |
| - |
94 |
| -impl<T: Internable + AsRef<U>, U: ?Sized> AsRef<U> for Interned<T> { |
95 |
| - fn as_ref(&self) -> &U { |
96 |
| - let l = T::intern_cache().lock().unwrap(); |
97 |
| - unsafe { mem::transmute::<&U, &U>(l.get(*self).as_ref()) } |
98 |
| - } |
99 |
| -} |
100 |
| - |
101 |
| -impl<T: Internable + PartialOrd> PartialOrd for Interned<T> { |
102 |
| - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { |
103 |
| - let l = T::intern_cache().lock().unwrap(); |
104 |
| - l.get(*self).partial_cmp(l.get(*other)) |
105 |
| - } |
106 |
| -} |
107 |
| - |
108 |
| -impl<T: Internable + Ord> Ord for Interned<T> { |
109 |
| - fn cmp(&self, other: &Self) -> Ordering { |
110 |
| - let l = T::intern_cache().lock().unwrap(); |
111 |
| - l.get(*self).cmp(l.get(*other)) |
112 |
| - } |
113 |
| -} |
114 |
| - |
115 |
| -struct TyIntern<T: Clone + Eq> { |
116 |
| - items: Vec<T>, |
117 |
| - set: HashMap<T, Interned<T>>, |
118 |
| -} |
119 |
| - |
120 |
| -impl<T: Hash + Clone + Eq> Default for TyIntern<T> { |
121 |
| - fn default() -> Self { |
122 |
| - TyIntern { items: Vec::new(), set: Default::default() } |
123 |
| - } |
124 |
| -} |
125 |
| - |
126 |
| -impl<T: Hash + Clone + Eq> TyIntern<T> { |
127 |
| - fn intern_borrow<B>(&mut self, item: &B) -> Interned<T> |
128 |
| - where |
129 |
| - B: Eq + Hash + ToOwned<Owned = T> + ?Sized, |
130 |
| - T: Borrow<B>, |
131 |
| - { |
132 |
| - if let Some(i) = self.set.get(item) { |
133 |
| - return *i; |
134 |
| - } |
135 |
| - let item = item.to_owned(); |
136 |
| - let interned = Interned(self.items.len(), PhantomData::<*const T>); |
137 |
| - self.set.insert(item.clone(), interned); |
138 |
| - self.items.push(item); |
139 |
| - interned |
140 |
| - } |
141 |
| - |
142 |
| - fn intern(&mut self, item: T) -> Interned<T> { |
143 |
| - if let Some(i) = self.set.get(&item) { |
144 |
| - return *i; |
145 |
| - } |
146 |
| - let interned = Interned(self.items.len(), PhantomData::<*const T>); |
147 |
| - self.set.insert(item.clone(), interned); |
148 |
| - self.items.push(item); |
149 |
| - interned |
150 |
| - } |
151 |
| - |
152 |
| - fn get(&self, i: Interned<T>) -> &T { |
153 |
| - &self.items[i.0] |
154 |
| - } |
155 |
| -} |
156 |
| - |
157 |
| -#[derive(Default)] |
158 |
| -pub struct Interner { |
159 |
| - strs: Mutex<TyIntern<String>>, |
160 |
| - paths: Mutex<TyIntern<PathBuf>>, |
161 |
| - lists: Mutex<TyIntern<Vec<String>>>, |
162 |
| -} |
163 |
| - |
164 |
| -trait Internable: Clone + Eq + Hash + 'static { |
165 |
| - fn intern_cache() -> &'static Mutex<TyIntern<Self>>; |
166 |
| - |
167 |
| - fn intern(self) -> Interned<Self> { |
168 |
| - Self::intern_cache().lock().unwrap().intern(self) |
169 |
| - } |
170 |
| -} |
171 |
| - |
172 |
| -impl Internable for String { |
173 |
| - fn intern_cache() -> &'static Mutex<TyIntern<Self>> { |
174 |
| - &INTERNER.strs |
175 |
| - } |
176 |
| -} |
177 |
| - |
178 |
| -impl Internable for PathBuf { |
179 |
| - fn intern_cache() -> &'static Mutex<TyIntern<Self>> { |
180 |
| - &INTERNER.paths |
181 |
| - } |
182 |
| -} |
183 |
| - |
184 |
| -impl Internable for Vec<String> { |
185 |
| - fn intern_cache() -> &'static Mutex<TyIntern<Self>> { |
186 |
| - &INTERNER.lists |
187 |
| - } |
188 |
| -} |
189 |
| - |
190 |
| -impl Interner { |
191 |
| - pub fn intern_str(&self, s: &str) -> Interned<String> { |
192 |
| - self.strs.lock().unwrap().intern_borrow(s) |
193 |
| - } |
194 |
| -} |
195 |
| - |
196 |
| -pub static INTERNER: LazyLock<Interner> = LazyLock::new(Interner::default); |
| 7 | +pub type Interned<T> = internment::Intern<T>; |
197 | 8 |
|
198 | 9 | /// This is essentially a `HashMap` which allows storing any type in its input and
|
199 | 10 | /// any type in its output. It is a write-once cache; values are never evicted,
|
|
0 commit comments