ferrum_plugin/typemap/
mod.rs1#![deny(missing_docs, warnings)]
2
3use uany::{UnsafeAny, UnsafeAnyExt};
6use std::any::{Any, TypeId};
7use std::collections::{hash_map, HashMap};
8use std::marker::PhantomData;
9
10use self::Entry::{Occupied, Vacant};
11
12pub use self::internals::{CloneAny, DebugAny};
13pub use self::internals::Implements;
14
15#[derive(Default, Debug)]
25pub struct TypeMap<A: ?Sized = UnsafeAny>
26where A: UnsafeAnyExt {
27 data: HashMap<TypeId, Box<A>>
28}
29
30impl<A: ?Sized> Clone for TypeMap<A>
31where A: UnsafeAnyExt, Box<A>: Clone { fn clone(&self) -> TypeMap<A> {
33 TypeMap { data: self.data.clone() }
34 }
35}
36
37pub type SendMap = TypeMap<UnsafeAny + Send>;
39
40pub type SyncMap = TypeMap<UnsafeAny + Sync>;
42
43pub type ShareMap = TypeMap<UnsafeAny + Send + Sync>;
45
46pub type CloneMap = TypeMap<CloneAny>;
48
49pub type ShareCloneMap = TypeMap<CloneAny + Send + Sync>;
51
52pub type DebugMap = TypeMap<DebugAny>;
54
55pub type ShareDebugMap = TypeMap<DebugAny + Send + Sync>;
57
58fn _assert_types() {
60 use std::fmt::Debug;
61
62 fn _assert_send<T: Send>() { }
63 fn _assert_sync<T: Sync>() { }
64 fn _assert_clone<T: Clone>() { }
65 fn _assert_debug<T: Debug>() { }
66
67 _assert_send::<SendMap>();
68 _assert_sync::<SyncMap>();
69 _assert_send::<ShareMap>();
70 _assert_sync::<ShareMap>();
71 _assert_clone::<CloneMap>();
72 _assert_debug::<DebugMap>();
73}
74
75pub trait Key: Any {
79 type Value: Any;
81}
82
83impl TypeMap {
84 pub fn new() -> TypeMap {
86 TypeMap::custom()
87 }
88}
89
90impl<A: UnsafeAnyExt + ?Sized> TypeMap<A> {
91 pub fn custom() -> TypeMap<A> {
96 TypeMap {
97 data: HashMap::new()
98 }
99 }
100
101 pub fn insert<K: Key>(&mut self, val: K::Value) -> Option<K::Value>
103 where K::Value: Any + Implements<A> {
104 self.data.insert(TypeId::of::<K>(), val.into_object()).map(|v| unsafe {
105 *v.downcast_unchecked::<K::Value>()
106 })
107 }
108
109 pub fn get<K: Key>(&self) -> Option<&K::Value>
111 where K::Value: Any + Implements<A> {
112 self.data.get(&TypeId::of::<K>()).map(|v| unsafe {
113 v.downcast_ref_unchecked::<K::Value>()
114 })
115 }
116
117 pub fn get_mut<K: Key>(&mut self) -> Option<&mut K::Value>
119 where K::Value: Any + Implements<A> {
120 self.data.get_mut(&TypeId::of::<K>()).map(|v| unsafe {
121 v.downcast_mut_unchecked::<K::Value>()
122 })
123 }
124
125 pub fn contains<K: Key>(&self) -> bool {
127 self.data.contains_key(&TypeId::of::<K>())
128 }
129
130 pub fn remove<K: Key>(&mut self) -> Option<K::Value>
134 where K::Value: Any + Implements<A> {
135 self.data.remove(&TypeId::of::<K>()).map(|v| unsafe {
136 *v.downcast_unchecked::<K::Value>()
137 })
138 }
139
140 pub fn entry<'a, K: Key>(&'a mut self) -> Entry<'a, K, A>
142 where K::Value: Any + Implements<A> {
143 match self.data.entry(TypeId::of::<K>()) {
144 hash_map::Entry::Occupied(e) => Occupied(OccupiedEntry { data: e, _marker: PhantomData }),
145 hash_map::Entry::Vacant(e) => Vacant(VacantEntry { data: e, _marker: PhantomData })
146 }
147 }
148
149 pub unsafe fn data(&self) -> &HashMap<TypeId, Box<A>> {
151 &self.data
152 }
153
154 pub unsafe fn data_mut(&mut self) -> &mut HashMap<TypeId, Box<A>> {
156 &mut self.data
157 }
158
159 pub fn len(&self) -> usize {
161 self.data.len()
162 }
163
164 pub fn is_empty(&self) -> bool {
166 self.data.is_empty()
167 }
168
169 pub fn clear(&mut self) {
171 self.data.clear()
172 }
173}
174
175pub enum Entry<'a, K, A: ?Sized + UnsafeAnyExt + 'a = UnsafeAny> {
177 Occupied(OccupiedEntry<'a, K, A>),
179 Vacant(VacantEntry<'a, K, A>)
181}
182
183impl<'a, K: Key, A: ?Sized + UnsafeAnyExt + 'a> Entry<'a, K, A> {
184 pub fn or_insert(self, default: K::Value) -> &'a mut K::Value
187 where K::Value: Any + Implements<A> {
188 match self {
189 Entry::Occupied(inner) => inner.into_mut(),
190 Entry::Vacant(inner) => inner.insert(default),
191 }
192 }
193
194 pub fn or_insert_with<F: FnOnce() -> K::Value>(self, default: F) -> &'a mut K::Value
197 where K::Value: Any + Implements<A> {
198 match self {
199 Entry::Occupied(inner) => inner.into_mut(),
200 Entry::Vacant(inner) => inner.insert(default()),
201 }
202 }
203}
204
205pub struct OccupiedEntry<'a, K, A: ?Sized + UnsafeAnyExt + 'a = UnsafeAny> {
207 data: hash_map::OccupiedEntry<'a, TypeId, Box<A>>,
208 _marker: PhantomData<K>
209}
210
211pub struct VacantEntry<'a, K, A: ?Sized + UnsafeAnyExt + 'a = UnsafeAny> {
213 data: hash_map::VacantEntry<'a, TypeId, Box<A>>,
214 _marker: PhantomData<K>
215}
216
217impl<'a, K: Key, A: UnsafeAnyExt + ?Sized> OccupiedEntry<'a, K, A> {
218 pub fn get(&self) -> &K::Value
220 where K::Value: Any + Implements<A> {
221 unsafe {
222 self.data.get().downcast_ref_unchecked()
223 }
224 }
225
226 pub fn get_mut(&mut self) -> &mut K::Value
228 where K::Value: Any + Implements<A> {
229 unsafe {
230 self.data.get_mut().downcast_mut_unchecked()
231 }
232 }
233
234 pub fn into_mut(self) -> &'a mut K::Value
236 where K::Value: Any + Implements<A> {
237 unsafe {
238 self.data.into_mut().downcast_mut_unchecked()
239 }
240 }
241
242 pub fn insert(&mut self, value: K::Value) -> K::Value
244 where K::Value: Any + Implements<A> {
245 unsafe {
246 *self.data.insert(value.into_object()).downcast_unchecked()
247 }
248 }
249
250 pub fn remove(self) -> K::Value
252 where K::Value: Any + Implements<A> {
253 unsafe {
254 *self.data.remove().downcast_unchecked()
255 }
256 }
257}
258
259impl<'a, K: Key, A: ?Sized + UnsafeAnyExt> VacantEntry<'a, K, A> {
260 pub fn insert(self, value: K::Value) -> &'a mut K::Value
262 where K::Value: Any + Implements<A> {
263 unsafe {
264 self.data.insert(value.into_object()).downcast_mut_unchecked()
265 }
266 }
267}
268
269mod internals;
270
271#[cfg(test)]
272mod test {
273 use super::{TypeMap, CloneMap, DebugMap, SendMap, Key};
274 use super::Entry::{Occupied, Vacant};
275
276 #[derive(Debug, PartialEq)]
277 struct KeyType;
278
279 #[derive(Clone, Debug, PartialEq)]
280 struct Value(u8);
281
282 impl Key for KeyType { type Value = Value; }
283
284 #[test] fn test_pairing() {
285 let mut map = TypeMap::new();
286 map.insert::<KeyType>(Value(100));
287 assert_eq!(*map.get::<KeyType>().unwrap(), Value(100));
288 assert!(map.contains::<KeyType>());
289 }
290
291 #[test] fn test_remove() {
292 let mut map = TypeMap::new();
293 map.insert::<KeyType>(Value(10));
294 assert!(map.contains::<KeyType>());
295 map.remove::<KeyType>();
296 assert!(!map.contains::<KeyType>());
297 }
298
299 #[test] fn test_entry() {
300 let mut map = TypeMap::new();
301 map.insert::<KeyType>(Value(20));
302 match map.entry::<KeyType>() {
303 Occupied(e) => {
304 assert_eq!(e.get(), &Value(20));
305 assert_eq!(e.remove(), Value(20));
306 },
307 _ => panic!("Unable to locate inserted item.")
308 }
309 assert!(!map.contains::<KeyType>());
310 match map.entry::<KeyType>() {
311 Vacant(e) => {
312 e.insert(Value(2));
313 },
314 _ => panic!("Found non-existant entry.")
315 }
316 assert!(map.contains::<KeyType>());
317 }
318
319 #[test] fn test_entry_or_insert() {
320 let mut map = TypeMap::new();
321 map.entry::<KeyType>().or_insert(Value(20)).0 += 1;
322 assert_eq!(map.get::<KeyType>().unwrap(), &Value(21));
323
324 map.entry::<KeyType>().or_insert(Value(100)).0 += 1;
326 assert_eq!(map.get::<KeyType>().unwrap(), &Value(22));
327 }
328
329 #[test] fn test_custom_bounds() {
330 let mut map: SendMap = TypeMap::custom();
331 map.insert::<KeyType>(Value(10));
332 assert!(map.contains::<KeyType>());
333 map.remove::<KeyType>();
334 assert!(!map.contains::<KeyType>());
335 }
336
337 #[test] fn test_clonemap() {
338 let mut map: CloneMap = TypeMap::custom();
339 map.insert::<KeyType>(Value(10));
340 assert!(map.contains::<KeyType>());
341 let cloned = map.clone();
342 assert_eq!(map.get::<KeyType>(), cloned.get::<KeyType>());
343 }
344
345 #[test] fn test_debugmap() {
346 let mut map: DebugMap = TypeMap::custom();
347 map.insert::<KeyType>(Value(10));
348 assert!(map.contains::<KeyType>());
349 }
350}