1 use std::any::{Any, TypeId}; 2 use std::borrow::Borrow; 3 use std::cell::RefCell; 4 use std::cmp::Ordering; 5 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::Mutex; 13 14 // FIXME: replace with std::lazy after it gets stabilized and reaches beta 15 use once_cell::sync::Lazy; 16 17 use crate::builder::Step; 18 19 pub struct Interned<T>(usize, PhantomData<*const T>); 20 21 impl<T: Internable + Default> Default for Interned<T> { default() -> Self22 fn default() -> Self { 23 T::default().intern() 24 } 25 } 26 27 impl<T> Copy for Interned<T> {} 28 impl<T> Clone for Interned<T> { clone(&self) -> Interned<T>29 fn clone(&self) -> Interned<T> { 30 *self 31 } 32 } 33 34 impl<T> PartialEq for Interned<T> { eq(&self, other: &Self) -> bool35 fn eq(&self, other: &Self) -> bool { 36 self.0 == other.0 37 } 38 } 39 impl<T> Eq for Interned<T> {} 40 41 impl PartialEq<str> for Interned<String> { eq(&self, other: &str) -> bool42 fn eq(&self, other: &str) -> bool { 43 *self == other 44 } 45 } 46 impl<'a> PartialEq<&'a str> for Interned<String> { eq(&self, other: &&str) -> bool47 fn eq(&self, other: &&str) -> bool { 48 **self == **other 49 } 50 } 51 impl<'a, T> PartialEq<&'a Interned<T>> for Interned<T> { eq(&self, other: &&Self) -> bool52 fn eq(&self, other: &&Self) -> bool { 53 self.0 == other.0 54 } 55 } 56 impl<'a, T> PartialEq<Interned<T>> for &'a Interned<T> { eq(&self, other: &Interned<T>) -> bool57 fn eq(&self, other: &Interned<T>) -> bool { 58 self.0 == other.0 59 } 60 } 61 62 unsafe impl<T> Send for Interned<T> {} 63 unsafe impl<T> Sync for Interned<T> {} 64 65 impl fmt::Display for Interned<String> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 67 let s: &str = &*self; 68 f.write_str(s) 69 } 70 } 71 72 impl<T, U: ?Sized + fmt::Debug> fmt::Debug for Interned<T> 73 where 74 Self: Deref<Target = U>, 75 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 77 let s: &U = &*self; 78 f.write_fmt(format_args!("{:?}", s)) 79 } 80 } 81 82 impl<T: Internable + Hash> Hash for Interned<T> { hash<H: Hasher>(&self, state: &mut H)83 fn hash<H: Hasher>(&self, state: &mut H) { 84 let l = T::intern_cache().lock().unwrap(); 85 l.get(*self).hash(state) 86 } 87 } 88 89 impl<T: Internable + Deref> Deref for Interned<T> { 90 type Target = T::Target; deref(&self) -> &Self::Target91 fn deref(&self) -> &Self::Target { 92 let l = T::intern_cache().lock().unwrap(); 93 unsafe { mem::transmute::<&Self::Target, &Self::Target>(l.get(*self)) } 94 } 95 } 96 97 impl<T: Internable + AsRef<U>, U: ?Sized> AsRef<U> for Interned<T> { as_ref(&self) -> &U98 fn as_ref(&self) -> &U { 99 let l = T::intern_cache().lock().unwrap(); 100 unsafe { mem::transmute::<&U, &U>(l.get(*self).as_ref()) } 101 } 102 } 103 104 impl<T: Internable + PartialOrd> PartialOrd for Interned<T> { partial_cmp(&self, other: &Self) -> Option<Ordering>105 fn partial_cmp(&self, other: &Self) -> Option<Ordering> { 106 let l = T::intern_cache().lock().unwrap(); 107 l.get(*self).partial_cmp(l.get(*other)) 108 } 109 } 110 111 impl<T: Internable + Ord> Ord for Interned<T> { cmp(&self, other: &Self) -> Ordering112 fn cmp(&self, other: &Self) -> Ordering { 113 let l = T::intern_cache().lock().unwrap(); 114 l.get(*self).cmp(l.get(*other)) 115 } 116 } 117 118 struct TyIntern<T: Clone + Eq> { 119 items: Vec<T>, 120 set: HashMap<T, Interned<T>>, 121 } 122 123 impl<T: Hash + Clone + Eq> Default for TyIntern<T> { default() -> Self124 fn default() -> Self { 125 TyIntern { items: Vec::new(), set: Default::default() } 126 } 127 } 128 129 impl<T: Hash + Clone + Eq> TyIntern<T> { intern_borrow<B>(&mut self, item: &B) -> Interned<T> where B: Eq + Hash + ToOwned<Owned = T> + ?Sized, T: Borrow<B>,130 fn intern_borrow<B>(&mut self, item: &B) -> Interned<T> 131 where 132 B: Eq + Hash + ToOwned<Owned = T> + ?Sized, 133 T: Borrow<B>, 134 { 135 if let Some(i) = self.set.get(&item) { 136 return *i; 137 } 138 let item = item.to_owned(); 139 let interned = Interned(self.items.len(), PhantomData::<*const T>); 140 self.set.insert(item.clone(), interned); 141 self.items.push(item); 142 interned 143 } 144 intern(&mut self, item: T) -> Interned<T>145 fn intern(&mut self, item: T) -> Interned<T> { 146 if let Some(i) = self.set.get(&item) { 147 return *i; 148 } 149 let interned = Interned(self.items.len(), PhantomData::<*const T>); 150 self.set.insert(item.clone(), interned); 151 self.items.push(item); 152 interned 153 } 154 get(&self, i: Interned<T>) -> &T155 fn get(&self, i: Interned<T>) -> &T { 156 &self.items[i.0] 157 } 158 } 159 160 #[derive(Default)] 161 pub struct Interner { 162 strs: Mutex<TyIntern<String>>, 163 paths: Mutex<TyIntern<PathBuf>>, 164 lists: Mutex<TyIntern<Vec<String>>>, 165 } 166 167 trait Internable: Clone + Eq + Hash + 'static { intern_cache() -> &'static Mutex<TyIntern<Self>>168 fn intern_cache() -> &'static Mutex<TyIntern<Self>>; 169 intern(self) -> Interned<Self>170 fn intern(self) -> Interned<Self> { 171 Self::intern_cache().lock().unwrap().intern(self) 172 } 173 } 174 175 impl Internable for String { intern_cache() -> &'static Mutex<TyIntern<Self>>176 fn intern_cache() -> &'static Mutex<TyIntern<Self>> { 177 &INTERNER.strs 178 } 179 } 180 181 impl Internable for PathBuf { intern_cache() -> &'static Mutex<TyIntern<Self>>182 fn intern_cache() -> &'static Mutex<TyIntern<Self>> { 183 &INTERNER.paths 184 } 185 } 186 187 impl Internable for Vec<String> { intern_cache() -> &'static Mutex<TyIntern<Self>>188 fn intern_cache() -> &'static Mutex<TyIntern<Self>> { 189 &INTERNER.lists 190 } 191 } 192 193 impl Interner { intern_str(&self, s: &str) -> Interned<String>194 pub fn intern_str(&self, s: &str) -> Interned<String> { 195 self.strs.lock().unwrap().intern_borrow(s) 196 } intern_string(&self, s: String) -> Interned<String>197 pub fn intern_string(&self, s: String) -> Interned<String> { 198 self.strs.lock().unwrap().intern(s) 199 } 200 intern_path(&self, s: PathBuf) -> Interned<PathBuf>201 pub fn intern_path(&self, s: PathBuf) -> Interned<PathBuf> { 202 self.paths.lock().unwrap().intern(s) 203 } 204 intern_list(&self, v: Vec<String>) -> Interned<Vec<String>>205 pub fn intern_list(&self, v: Vec<String>) -> Interned<Vec<String>> { 206 self.lists.lock().unwrap().intern(v) 207 } 208 } 209 210 pub static INTERNER: Lazy<Interner> = Lazy::new(Interner::default); 211 212 /// This is essentially a `HashMap` which allows storing any type in its input and 213 /// any type in its output. It is a write-once cache; values are never evicted, 214 /// which means that references to the value can safely be returned from the 215 /// `get()` method. 216 #[derive(Debug)] 217 pub struct Cache( 218 RefCell< 219 HashMap< 220 TypeId, 221 Box<dyn Any>, // actually a HashMap<Step, Interned<Step::Output>> 222 >, 223 >, 224 ); 225 226 impl Cache { new() -> Cache227 pub fn new() -> Cache { 228 Cache(RefCell::new(HashMap::new())) 229 } 230 put<S: Step>(&self, step: S, value: S::Output)231 pub fn put<S: Step>(&self, step: S, value: S::Output) { 232 let mut cache = self.0.borrow_mut(); 233 let type_id = TypeId::of::<S>(); 234 let stepcache = cache 235 .entry(type_id) 236 .or_insert_with(|| Box::new(HashMap::<S, S::Output>::new())) 237 .downcast_mut::<HashMap<S, S::Output>>() 238 .expect("invalid type mapped"); 239 assert!(!stepcache.contains_key(&step), "processing {:?} a second time", step); 240 stepcache.insert(step, value); 241 } 242 get<S: Step>(&self, step: &S) -> Option<S::Output>243 pub fn get<S: Step>(&self, step: &S) -> Option<S::Output> { 244 let mut cache = self.0.borrow_mut(); 245 let type_id = TypeId::of::<S>(); 246 let stepcache = cache 247 .entry(type_id) 248 .or_insert_with(|| Box::new(HashMap::<S, S::Output>::new())) 249 .downcast_mut::<HashMap<S, S::Output>>() 250 .expect("invalid type mapped"); 251 stepcache.get(step).cloned() 252 } 253 } 254 255 #[cfg(test)] 256 impl Cache { all<S: Ord + Clone + Step>(&mut self) -> Vec<(S, S::Output)>257 pub fn all<S: Ord + Clone + Step>(&mut self) -> Vec<(S, S::Output)> { 258 let cache = self.0.get_mut(); 259 let type_id = TypeId::of::<S>(); 260 let mut v = cache 261 .remove(&type_id) 262 .map(|b| b.downcast::<HashMap<S, S::Output>>().expect("correct type")) 263 .map(|m| m.into_iter().collect::<Vec<_>>()) 264 .unwrap_or_default(); 265 v.sort_by_key(|(s, _)| s.clone()); 266 v 267 } 268 contains<S: Step>(&self) -> bool269 pub fn contains<S: Step>(&self) -> bool { 270 self.0.borrow().contains_key(&TypeId::of::<S>()) 271 } 272 } 273