1use std::any::{Any, TypeId};
4use std::collections::hash_map::IntoIter;
5use std::collections::hash_map::{
6 Entry as HashMapEntry, OccupiedEntry as HashMapOccupiedEntry, VacantEntry as HashMapVacantEntry,
7};
8use std::collections::HashMap;
9use std::fmt::Debug;
10use std::iter::FromIterator;
11use std::marker::PhantomData;
12
13pub type DefaultStorage = dyn Any + Send + Sync;
15
16pub trait CloneableStorage: Any + Send + Sync {
19 #[doc(hidden)]
20 fn clone_storage(&self) -> Box<dyn CloneableStorage>;
21}
22
23impl<T: Any + Send + Sync + Clone> CloneableStorage for T {
24 fn clone_storage(&self) -> Box<dyn CloneableStorage> {
25 Box::new(self.clone())
26 }
27}
28
29impl Clone for Box<dyn CloneableStorage> {
30 fn clone(&self) -> Self {
31 (**self).clone_storage()
32 }
33}
34
35pub trait DebuggableStorage: Any + Send + Sync + Debug {}
38impl<T: Any + Send + Sync + Debug> DebuggableStorage for T {}
39
40pub trait CloneDebuggableStorage: DebuggableStorage {
43 #[doc(hidden)]
44 fn clone_storage(&self) -> Box<dyn CloneDebuggableStorage>;
45}
46
47impl<T: DebuggableStorage + Clone> CloneDebuggableStorage for T {
48 fn clone_storage(&self) -> Box<dyn CloneDebuggableStorage> {
49 Box::new(self.clone())
50 }
51}
52
53impl Clone for Box<dyn CloneDebuggableStorage> {
54 fn clone(&self) -> Self {
55 (**self).clone_storage()
56 }
57}
58
59#[doc(hidden)]
60pub trait IntoBox<T: ?Sized> {
61 fn into_box(self) -> Box<T>;
62}
63
64impl<T: Any + Send + Sync> IntoBox<(dyn Any + Send + Sync)> for T {
65 fn into_box(self) -> Box<dyn Any + Send + Sync> {
66 Box::new(self)
67 }
68}
69
70impl<T: CloneableStorage> IntoBox<dyn CloneableStorage> for T {
71 fn into_box(self) -> Box<dyn CloneableStorage> {
72 Box::new(self)
73 }
74}
75
76impl<T: DebuggableStorage> IntoBox<dyn DebuggableStorage> for T {
77 fn into_box(self) -> Box<dyn DebuggableStorage> {
78 Box::new(self)
79 }
80}
81
82impl<T: CloneDebuggableStorage> IntoBox<dyn CloneDebuggableStorage> for T {
83 fn into_box(self) -> Box<dyn CloneDebuggableStorage> {
84 Box::new(self)
85 }
86}
87
88pub trait TypeMapKey: Any {
93 type Value: Any + Send + Sync;
95}
96
97pub struct TypeMap<S: ?Sized = DefaultStorage>(HashMap<TypeId, Box<S>>);
103
104impl TypeMap {
105 #[inline]
107 pub fn new() -> Self {
108 Self::custom()
109 }
110}
111
112impl<S: ?Sized + Any + Send + Sync> TypeMap<S> {
113 #[inline]
115 pub fn custom() -> Self {
116 Self(HashMap::new())
117 }
118
119 #[inline]
121 pub fn len(&self) -> usize {
122 self.0.len()
123 }
124
125 #[inline]
127 pub fn is_empty(&self) -> bool {
128 self.0.is_empty()
129 }
130
131 #[inline]
133 pub fn clear(&mut self) {
134 self.0.clear();
135 }
136
137 #[inline]
154 pub fn contains_key<T>(&self) -> bool
155 where
156 T: TypeMapKey,
157 {
158 self.0.contains_key(&TypeId::of::<T>())
159 }
160
161 #[inline]
182 pub fn insert<T>(&mut self, value: T::Value)
183 where
184 T: TypeMapKey,
185 T::Value: IntoBox<S>,
186 {
187 self.0.insert(TypeId::of::<T>(), value.into_box());
188 }
189
190 #[inline]
194 pub fn entry<T>(&mut self) -> Entry<'_, T, S>
195 where
196 T: TypeMapKey,
197 T::Value: IntoBox<S>,
198 {
199 match self.0.entry(TypeId::of::<T>()) {
200 HashMapEntry::Occupied(entry) => Entry::Occupied(OccupiedEntry {
201 entry,
202 _marker: PhantomData,
203 }),
204 HashMapEntry::Vacant(entry) => Entry::Vacant(VacantEntry {
205 entry,
206 _marker: PhantomData,
207 }),
208 }
209 }
210
211 #[inline]
231 pub fn get<T>(&self) -> Option<&T::Value>
232 where
233 T: TypeMapKey,
234 T::Value: IntoBox<S>,
235 {
236 self.0
237 .get(&TypeId::of::<T>())
238 .map(|b| unsafe { &*((&**b) as *const _ as *const T::Value) })
239 }
240
241 #[inline]
263 pub fn get_mut<T>(&mut self) -> Option<&mut T::Value>
264 where
265 T: TypeMapKey,
266 T::Value: IntoBox<S>,
267 {
268 self.0
269 .get_mut(&TypeId::of::<T>())
270 .map(|b| unsafe { &mut *((&mut **b) as *mut _ as *mut T::Value) })
271 }
272
273 #[inline]
292 pub fn remove<T>(&mut self) -> Option<T::Value>
293 where
294 T: TypeMapKey,
295 T::Value: IntoBox<S>,
296 {
297 self.0
298 .remove(&TypeId::of::<T>())
299 .map(|b| *unsafe { Box::from_raw(Box::into_raw(b) as *mut T::Value) })
300 }
301}
302
303impl<S: ?Sized> Default for TypeMap<S> {
304 fn default() -> Self {
305 Self(HashMap::default())
306 }
307}
308
309impl<S: ?Sized + DebuggableStorage> Debug for TypeMap<S> {
310 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
311 Debug::fmt(&self.0, f)
312 }
313}
314
315impl<S: ?Sized> Clone for TypeMap<S>
316where
317 Box<S>: Clone,
318{
319 fn clone(&self) -> Self {
320 Self(self.0.clone())
321 }
322}
323
324impl<S: ?Sized> Extend<(TypeId, Box<S>)> for TypeMap<S> {
325 fn extend<T: IntoIterator<Item = (TypeId, Box<S>)>>(&mut self, iter: T) {
326 self.0.extend(iter)
327 }
328}
329
330impl<S: ?Sized> IntoIterator for TypeMap<S> {
331 type Item = (TypeId, Box<S>);
332 type IntoIter = IntoIter<TypeId, Box<S>>;
333
334 fn into_iter(self) -> Self::IntoIter {
335 self.0.into_iter()
336 }
337}
338
339impl<S: ?Sized> FromIterator<(TypeId, Box<S>)> for TypeMap<S> {
340 fn from_iter<T: IntoIterator<Item = (TypeId, Box<S>)>>(iter: T) -> Self {
341 Self(HashMap::from_iter(iter))
342 }
343}
344
345pub enum Entry<'a, K, S: ?Sized = DefaultStorage>
355where
356 K: TypeMapKey,
357{
358 Occupied(OccupiedEntry<'a, K, S>),
359 Vacant(VacantEntry<'a, K, S>),
360}
361
362impl<'a, K, S> Entry<'a, K, S>
363where
364 K: TypeMapKey,
365 K::Value: IntoBox<S>,
366 S: ?Sized + Any + Send + Sync,
367{
368 #[inline]
369 pub fn or_insert(self, value: K::Value) -> &'a mut K::Value {
370 match self {
371 Entry::Occupied(entry) => entry.into_mut(),
372 Entry::Vacant(entry) => entry.insert(value),
373 }
374 }
375
376 #[inline]
377 pub fn or_insert_with<F>(self, f: F) -> &'a mut K::Value
378 where
379 F: FnOnce() -> K::Value,
380 {
381 match self {
382 Entry::Occupied(entry) => entry.into_mut(),
383 Entry::Vacant(entry) => entry.insert(f()),
384 }
385 }
386
387 #[inline]
388 pub fn and_modify<F>(self, f: F) -> Self
389 where
390 F: FnOnce(&mut K::Value),
391 {
392 match self {
393 Entry::Occupied(mut entry) => {
394 f(entry.get_mut());
395 Entry::Occupied(entry)
396 }
397 Entry::Vacant(entry) => Entry::Vacant(entry),
398 }
399 }
400}
401
402impl<'a, K, S> Entry<'a, K, S>
403where
404 K: TypeMapKey,
405 K::Value: Default + IntoBox<S>,
406 S: ?Sized + Any + Send + Sync,
407{
408 #[inline]
409 pub fn or_default(self) -> &'a mut K::Value {
410 self.or_insert_with(<K::Value as Default>::default)
411 }
412}
413
414pub struct OccupiedEntry<'a, K, S: ?Sized = DefaultStorage>
415where
416 K: TypeMapKey,
417{
418 entry: HashMapOccupiedEntry<'a, TypeId, Box<S>>,
419 _marker: PhantomData<&'a K::Value>,
420}
421
422impl<'a, K, S> OccupiedEntry<'a, K, S>
423where
424 K: TypeMapKey,
425 K::Value: IntoBox<S>,
426 S: ?Sized + Any + Send + Sync,
427{
428 #[inline]
429 pub fn get(&self) -> &K::Value {
430 unsafe { &*((&**self.entry.get()) as *const _ as *const K::Value) }
431 }
432
433 #[inline]
434 pub fn get_mut(&mut self) -> &mut K::Value {
435 unsafe { &mut *((&mut **self.entry.get_mut()) as *mut _ as *mut K::Value) }
436 }
437
438 #[inline]
439 pub fn into_mut(self) -> &'a mut K::Value {
440 unsafe { &mut *((&mut **self.entry.into_mut()) as *mut _ as *mut K::Value) }
441 }
442
443 #[inline]
444 pub fn insert(&mut self, value: K::Value) {
445 self.entry.insert(value.into_box());
446 }
447
448 #[inline]
449 pub fn remove(self) {
450 self.entry.remove();
451 }
452}
453
454pub struct VacantEntry<'a, K, S: ?Sized = DefaultStorage>
455where
456 K: TypeMapKey,
457{
458 entry: HashMapVacantEntry<'a, TypeId, Box<S>>,
459 _marker: PhantomData<&'a K::Value>,
460}
461
462impl<'a, K, S> VacantEntry<'a, K, S>
463where
464 K: TypeMapKey,
465 K::Value: IntoBox<S>,
466 S: ?Sized + Any + Send + Sync,
467{
468 #[inline]
469 pub fn insert(self, value: K::Value) -> &'a mut K::Value {
470 let value = self.entry.insert(value.into_box());
471 unsafe { &mut *((&mut **value) as *mut _ as *mut K::Value) }
472 }
473}
474
475#[cfg(test)]
476mod test {
477 use super::*;
478
479 struct Counter;
480
481 impl TypeMapKey for Counter {
482 type Value = u64;
483 }
484
485 #[test]
486 fn typemap_counter() {
487 let mut map = TypeMap::new();
488
489 assert_eq!(map.len(), 0);
490 assert!(map.is_empty());
491
492 map.insert::<Counter>(0);
493 assert_eq!(map.len(), 1);
494 assert!(!map.is_empty());
495
496 assert_eq!(*map.get::<Counter>().unwrap(), 0);
497
498 for _ in 0..100 {
499 *map.get_mut::<Counter>().unwrap() += 1;
500 }
501
502 assert_eq!(*map.get::<Counter>().unwrap(), 100);
503
504 map.clear();
505 assert!(map.get::<Counter>().is_none());
506 assert_eq!(map.len(), 0);
507 assert!(map.is_empty());
508 }
509
510 #[test]
511 fn typemap_entry() {
512 let mut map = TypeMap::new();
513
514 assert_eq!(map.get::<Counter>(), None);
515 *map.entry::<Counter>().or_insert(0) += 42;
516 assert_eq!(*map.get::<Counter>().unwrap(), 42);
517 }
518
519 struct Text;
520
521 impl TypeMapKey for Text {
522 type Value = String;
523 }
524
525 #[test]
526 fn typemap_remove() {
527 let mut map = TypeMap::new();
528
529 map.insert::<Text>(String::from("foobar"));
530
531 assert_eq!(map.get::<Text>().unwrap(), "foobar");
533
534 let original: String = map.remove::<Text>().unwrap();
536 assert_eq!(original, "foobar");
537
538 assert!(map.get::<Text>().is_none());
540 }
541
542 #[test]
543 fn typemap_default() {
544 fn ensure_default<T: Default>() {}
545
546 ensure_default::<TypeMap>();
547
548 let map = TypeMap::<DefaultStorage>::default();
549 assert!(map.get::<Text>().is_none());
550 }
551
552 #[test]
553 fn typemap_iter() {
554 let mut map = TypeMap::new();
555 map.insert::<Text>(String::from("foobar"));
556
557 let mut iterator = map.into_iter();
559
560 assert_eq!(iterator.next().unwrap().0, TypeId::of::<Text>());
562 }
563
564 #[test]
565 fn typemap_extend() {
566 let mut map = TypeMap::new();
567 map.insert::<Text>(String::from("foobar"));
568
569 let mut map_2 = TypeMap::new();
570 map_2.extend(map);
572
573 let original = map_2.get::<Text>().unwrap();
575 assert_eq!(original, "foobar");
576 }
577
578 fn is_debug<T: Debug>() {}
579 fn is_clone<T: Clone>() {}
580
581 #[test]
582 fn typemap_debug() {
583 is_debug::<i32>();
584 is_debug::<TypeMap<dyn DebuggableStorage>>();
585 is_debug::<TypeMap<dyn CloneDebuggableStorage>>();
586 }
587
588 #[test]
589 fn typemap_clone() {
590 is_clone::<i32>();
591 is_clone::<TypeMap<dyn CloneableStorage>>();
592 is_clone::<TypeMap<dyn CloneDebuggableStorage>>();
593
594 let mut map = TypeMap::<dyn CloneableStorage>::custom();
595 map.insert::<Text>(String::from("foo"));
596
597 let map_2 = map.clone();
598 assert_eq!(*map_2.get::<Text>().unwrap(), "foo");
599
600 let mut map = TypeMap::<dyn CloneDebuggableStorage>::custom();
601 map.insert::<Text>(String::from("foo"));
602
603 let map_2 = map.clone();
604 assert_eq!(*map_2.get::<Text>().unwrap(), "foo");
605 }
606}