1 use std::any::{Any, TypeId};
2 use std::borrow::Borrow;
3 use std::cell::RefCell;
4 use std::collections::HashMap;
5 use std::convert::AsRef;
8 use std::hash::{Hash, Hasher};
9 use std::marker::PhantomData;
12 use std::path::{Path, PathBuf};
14 use std::cmp::{PartialOrd, Ord, Ordering};
16 use crate::builder::Step;
18 pub struct Interned<T>(usize, PhantomData<*const T>);
20 impl Default for Interned<String> {
21 fn default() -> Self {
22 INTERNER.intern_string(String::default())
26 impl Default for Interned<PathBuf> {
27 fn default() -> Self {
28 INTERNER.intern_path(PathBuf::default())
32 impl<T> Copy for Interned<T> {}
33 impl<T> Clone for Interned<T> {
34 fn clone(&self) -> Interned<T> {
39 impl<T> PartialEq for Interned<T> {
40 fn eq(&self, other: &Self) -> bool {
44 impl<T> Eq for Interned<T> {}
46 impl PartialEq<str> for Interned<String> {
47 fn eq(&self, other: &str) -> bool {
51 impl<'a> PartialEq<&'a str> for Interned<String> {
52 fn eq(&self, other: &&str) -> bool {
56 impl<'a, T> PartialEq<&'a Interned<T>> for Interned<T> {
57 fn eq(&self, other: &&Self) -> bool {
61 impl<'a, T> PartialEq<Interned<T>> for &'a Interned<T> {
62 fn eq(&self, other: &Interned<T>) -> bool {
67 unsafe impl<T> Send for Interned<T> {}
68 unsafe impl<T> Sync for Interned<T> {}
70 impl fmt::Display for Interned<String> {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77 impl fmt::Debug for Interned<String> {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80 f.write_fmt(format_args!("{:?}", s))
83 impl fmt::Debug for Interned<PathBuf> {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 let s: &Path = &*self;
86 f.write_fmt(format_args!("{:?}", s))
90 impl Hash for Interned<String> {
91 fn hash<H: Hasher>(&self, state: &mut H) {
92 let l = INTERNER.strs.lock().unwrap();
93 l.get(*self).hash(state)
97 impl Hash for Interned<PathBuf> {
98 fn hash<H: Hasher>(&self, state: &mut H) {
99 let l = INTERNER.paths.lock().unwrap();
100 l.get(*self).hash(state)
104 impl Deref for Interned<String> {
106 fn deref(&self) -> &'static str {
107 let l = INTERNER.strs.lock().unwrap();
108 unsafe { mem::transmute::<&str, &'static str>(l.get(*self)) }
112 impl Deref for Interned<PathBuf> {
114 fn deref(&self) -> &'static Path {
115 let l = INTERNER.paths.lock().unwrap();
116 unsafe { mem::transmute::<&Path, &'static Path>(l.get(*self)) }
120 impl AsRef<Path> for Interned<PathBuf> {
121 fn as_ref(&self) -> &'static Path {
122 let l = INTERNER.paths.lock().unwrap();
123 unsafe { mem::transmute::<&Path, &'static Path>(l.get(*self)) }
127 impl AsRef<Path> for Interned<String> {
128 fn as_ref(&self) -> &'static Path {
129 let l = INTERNER.strs.lock().unwrap();
130 unsafe { mem::transmute::<&Path, &'static Path>(l.get(*self).as_ref()) }
134 impl AsRef<OsStr> for Interned<PathBuf> {
135 fn as_ref(&self) -> &'static OsStr {
136 let l = INTERNER.paths.lock().unwrap();
137 unsafe { mem::transmute::<&OsStr, &'static OsStr>(l.get(*self).as_ref()) }
141 impl AsRef<OsStr> for Interned<String> {
142 fn as_ref(&self) -> &'static OsStr {
143 let l = INTERNER.strs.lock().unwrap();
144 unsafe { mem::transmute::<&OsStr, &'static OsStr>(l.get(*self).as_ref()) }
148 impl PartialOrd<Interned<String>> for Interned<String> {
149 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
150 let l = INTERNER.strs.lock().unwrap();
151 l.get(*self).partial_cmp(l.get(*other))
155 impl Ord for Interned<String> {
156 fn cmp(&self, other: &Self) -> Ordering {
157 let l = INTERNER.strs.lock().unwrap();
158 l.get(*self).cmp(l.get(*other))
162 struct TyIntern<T: Hash + Clone + Eq> {
164 set: HashMap<T, Interned<T>>,
167 impl<T: Hash + Clone + Eq> Default for TyIntern<T> {
168 fn default() -> Self {
171 set: Default::default(),
176 impl<T: Hash + Clone + Eq> TyIntern<T> {
177 fn intern_borrow<B>(&mut self, item: &B) -> Interned<T>
179 B: Eq + Hash + ToOwned<Owned=T> + ?Sized,
182 if let Some(i) = self.set.get(&item) {
185 let item = item.to_owned();
186 let interned = Interned(self.items.len(), PhantomData::<*const T>);
187 self.set.insert(item.clone(), interned);
188 self.items.push(item);
192 fn intern(&mut self, item: T) -> Interned<T> {
193 if let Some(i) = self.set.get(&item) {
196 let interned = Interned(self.items.len(), PhantomData::<*const T>);
197 self.set.insert(item.clone(), interned);
198 self.items.push(item);
202 fn get(&self, i: Interned<T>) -> &T {
208 pub struct Interner {
209 strs: Mutex<TyIntern<String>>,
210 paths: Mutex<TyIntern<PathBuf>>,
214 pub fn intern_str(&self, s: &str) -> Interned<String> {
215 self.strs.lock().unwrap().intern_borrow(s)
217 pub fn intern_string(&self, s: String) -> Interned<String> {
218 self.strs.lock().unwrap().intern(s)
221 pub fn intern_path(&self, s: PathBuf) -> Interned<PathBuf> {
222 self.paths.lock().unwrap().intern(s)
227 pub static ref INTERNER: Interner = Interner::default();
230 /// This is essentially a `HashMap` which allows storing any type in its input and
231 /// any type in its output. It is a write-once cache; values are never evicted,
232 /// which means that references to the value can safely be returned from the
238 Box<dyn Any>, // actually a HashMap<Step, Interned<Step::Output>>
243 pub fn new() -> Cache {
244 Cache(RefCell::new(HashMap::new()))
247 pub fn put<S: Step>(&self, step: S, value: S::Output) {
248 let mut cache = self.0.borrow_mut();
249 let type_id = TypeId::of::<S>();
250 let stepcache = cache.entry(type_id)
251 .or_insert_with(|| Box::new(HashMap::<S, S::Output>::new()))
252 .downcast_mut::<HashMap<S, S::Output>>()
253 .expect("invalid type mapped");
254 assert!(!stepcache.contains_key(&step), "processing {:?} a second time", step);
255 stepcache.insert(step, value);
258 pub fn get<S: Step>(&self, step: &S) -> Option<S::Output> {
259 let mut cache = self.0.borrow_mut();
260 let type_id = TypeId::of::<S>();
261 let stepcache = cache.entry(type_id)
262 .or_insert_with(|| Box::new(HashMap::<S, S::Output>::new()))
263 .downcast_mut::<HashMap<S, S::Output>>()
264 .expect("invalid type mapped");
265 stepcache.get(step).cloned()
269 pub fn all<S: Ord + Copy + Step>(&mut self) -> Vec<(S, S::Output)> {
270 let cache = self.0.get_mut();
271 let type_id = TypeId::of::<S>();
272 let mut v = cache.remove(&type_id)
273 .map(|b| b.downcast::<HashMap<S, S::Output>>().expect("correct type"))
274 .map(|m| m.into_iter().collect::<Vec<_>>())
275 .unwrap_or_default();
276 v.sort_by_key(|&(a, _)| a);
281 pub fn contains<S: Step>(&self) -> bool {
282 self.0.borrow().contains_key(&TypeId::of::<S>())