1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use std::any::{type_name, Any, TypeId};
use std::collections::{HashMap, HashSet};
use std::hash::{BuildHasherDefault, Hasher};

// Copied/inspired from Axum's extensions.
// With TypeIds as keys, there's no need to hash them. They are already hashes
// themselves, coming from the compiler. The IdHasher just holds the u64 of
// the TypeId, and then returns it.
#[derive(Default)]
struct IdHasher(u64);

impl Hasher for IdHasher {
    fn write(&mut self, _: &[u8]) {
        unreachable!("TypeId calls write_u64");
    }

    #[inline]
    fn write_u64(&mut self, id: u64) {
        self.0 = id;
    }

    #[inline]
    fn finish(&self) -> u64 {
        self.0
    }
}

/// Holds values of different types and accessed by TypeId.
#[derive(Default)]
pub struct AnyMap {
    // Key is TypeId, value is heap-allocated Box<dyn Any + Send + Sync>
    map: HashMap<
        TypeId,
        Box<dyn Any + Send + Sync>,
        BuildHasherDefault<IdHasher>,
    >,
    known_types: HashSet<String>,
}

impl AnyMap {
    /// Returns a reference to value of type T if exists.
    pub fn get<T: Send + Sync + 'static>(&self) -> Option<&T> {
        self.map
            .get(&TypeId::of::<T>())
            // downcast_ref returns a reference to the boxed value if it is of
            // type T.
            .and_then(|boxed| (&**boxed as &(dyn Any + 'static)).downcast_ref())
    }

    /// Returns a mutable reference to value of type T if exists.
    pub fn get_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut T> {
        self.map.get_mut(&TypeId::of::<T>()).and_then(|boxed| {
            (&mut **boxed as &mut (dyn Any + 'static)).downcast_mut()
        })
    }

    /// Inserts a value into the collected arguments. If the value already
    /// exists, it will be returned.
    pub fn insert<T: Send + Sync + 'static>(&mut self, val: T) -> Option<T> {
        self.known_types.insert(type_name::<T>().to_string());
        self.map
            .insert(TypeId::of::<T>(), Box::new(val))
            .and_then(|boxed| {
                (boxed as Box<dyn Any + 'static>)
                    .downcast()
                    .ok()
                    .map(|boxed| *boxed)
            })
    }

    pub fn known_types(&self) -> Vec<String> {
        self.known_types.iter().cloned().collect()
    }

    #[inline]
    pub fn clear(&mut self) {
        self.map.clear();
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.map.is_empty()
    }

    #[cfg(test)]
    pub fn len(&self) -> usize {
        self.map.len()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    // Write tests for AnyMap
    #[test]
    fn test_anymap() {
        #[derive(Debug, PartialEq)]
        struct MyType(i32);

        let mut map = AnyMap::default();
        assert_eq!(0, map.len());

        assert_eq!(None, map.insert(1u32));
        let x = map.get::<u32>().unwrap();
        assert_eq!(1, *x);

        map.insert("hello".to_string());
        assert_eq!(2, map.len());
        assert_eq!("hello", *map.get::<String>().unwrap());

        assert_eq!(None, map.get::<MyType>());

        map.insert(MyType(42));
        assert_eq!(3, map.len());
        assert_eq!(MyType(42), *map.get::<MyType>().unwrap());

        assert_eq!(MyType(42), map.insert(MyType(43)).unwrap());

        map.clear();

        assert_eq!(0, map.len());
        assert!(map.is_empty());
        assert_eq!(None, map.insert(MyType(43)));
    }
}