Skip to main content

any_container/
multimap.rs

1use std::any::{Any, TypeId};
2use std::collections::HashMap;
3use std::fmt;
4use std::hash::BuildHasherDefault;
5
6use crate::boxed::AnyCloneBox;
7use crate::utils::IdHasher;
8use crate::vec::{AnyVec, AnyVecMutRef};
9
10/// A type-erased multimap storing multiple values per type.
11///
12/// `AnyMultiMap` allows storing multiple values of the same type, with each
13/// type identified by its `TypeId`. Values are stored in vectors behind
14/// trait objects, enabling type-erased access while maintaining type safety.
15///
16/// # Examples
17///
18/// ```
19/// use any_container::AnyMultiMap;
20///
21/// let mut multimap = AnyMultiMap::new();
22/// multimap.insert(1i32);
23/// multimap.insert(2i32);
24/// multimap.insert("hello".to_string());
25///
26/// assert_eq!(multimap.len::<i32>(), 2);
27/// assert_eq!(multimap.get::<i32>(), &[1, 2]);
28///
29/// assert_eq!(multimap.len::<String>(), 1);
30/// assert_eq!(multimap.get::<String>(), &["hello".to_string()]);
31/// ```
32#[repr(transparent)]
33pub struct AnyMultiMap {
34    // A map from a TypeId to a vector of values of that type
35    map: HashMap<TypeId, AnyVec, BuildHasherDefault<IdHasher>>,
36}
37
38impl Default for AnyMultiMap {
39    fn default() -> Self {
40        Self::new()
41    }
42}
43
44impl AnyMultiMap {
45    /// Creates a new empty `AnyMultiMap`.
46    pub fn new() -> AnyMultiMap {
47        AnyMultiMap {
48            map: HashMap::default(),
49        }
50    }
51
52    /// Returns the number of different types stored in the `AnyMultiMap`.
53    ///
54    /// This counts unique types, not the total number of values.
55    pub fn type_count(&self) -> usize {
56        self.map.len()
57    }
58
59    /// Returns the number of values of type `T` stored in the `AnyMultiMap`.
60    pub fn len<T: Any + Send + Sync>(&self) -> usize {
61        self.map
62            .get(&TypeId::of::<T>())
63            .map(|vec| vec.len())
64            .unwrap_or(0)
65    }
66
67    /// Returns the total number of values stored in the `AnyMultiMap`, across all types.
68    pub fn len_total(&self) -> usize {
69        self.map.values().map(|vec| vec.len()).sum()
70    }
71
72    /// Returns `true` if there are values of type `T` stored in the `AnyMultiMap`.
73    pub fn contains<T: Any + Send + Sync>(&self) -> bool {
74        self.map
75            .get(&TypeId::of::<T>())
76            .map(|vec| !vec.is_empty())
77            .unwrap_or(false)
78    }
79
80    /// Returns `true` if there are any values stored in the `AnyMultiMap`, across all types.
81    pub fn contains_any(&self) -> bool {
82        self.map.values().any(|vec| !vec.is_empty())
83    }
84
85    /// Returns `true` if there are no values of type `T` stored in the `AnyMultiMap`.
86    pub fn is_empty<T: Any + Send + Sync>(&self) -> bool {
87        !self.contains::<T>()
88    }
89
90    /// Returns `true` if there are no values stored in the `AnyMultiMap`, across all types.
91    pub fn is_completely_empty(&self) -> bool {
92        !self.contains_any()
93    }
94
95    /// Removes all values of type `T` from the `AnyMultiMap`.
96    pub fn clear<T: Any + Send + Sync>(&mut self) {
97        self.map.remove(&TypeId::of::<T>());
98    }
99
100    /// Removes all values from the `AnyMultiMap`, across all types.
101    pub fn clear_all(&mut self) {
102        self.map.clear();
103    }
104
105    /// Returns a slice of all values of type `T` stored in the `AnyMultiMap`.
106    /// If no values of type `T` exist, an empty slice is returned.
107    pub fn get<T: Any + Send + Sync>(&self) -> &[T] {
108        self.map
109            .get(&TypeId::of::<T>())
110            .map(|vec| {
111                debug_assert_eq!(
112                    vec.elem_type_id(),
113                    TypeId::of::<T>(),
114                    "TypeId mismatch in AnyMultiMap::get. This should never happen!"
115                );
116                unsafe {
117                    // Safety: The invariants guarantee that the vec is of the appropriate type
118                    vec.get_unchecked()
119                }
120            })
121            .unwrap_or(&[])
122    }
123
124    /// Returns a mutable reference to the vector values of type `T` stored in the `AnyMultiMap`.
125    /// If no values of type `T` exist, a new vector is created and returned.
126    /// This method is useful for adding multiple values of the same type efficiently.
127    pub fn get_mut<T: Any + Send + Sync>(&mut self) -> AnyVecMutRef<'_, T> {
128        let vec = self
129            .map
130            .entry(TypeId::of::<T>())
131            .or_insert_with(|| AnyVec::new::<T>());
132
133        debug_assert_eq!(
134            vec.elem_type_id(),
135            TypeId::of::<T>(),
136            "TypeId mismatch in AnyMultiMap::get_mut. This should never happen!"
137        );
138        unsafe {
139            // Safety: The invariants guarantee that the vec is of the appropriate type
140            vec.get_mut_unchecked()
141        }
142    }
143
144    /// Inserts a value of type `T` into the `AnyMultiMap`.
145    ///
146    /// ## Note
147    ///
148    /// This is a convenience method that calls `get_mut` and pushes the value into the vector.
149    /// If you need to insert multiple values of the same type, consider using `get_mut` directly
150    /// to avoid repeated lookups.
151    pub fn insert<T: Any + Send + Sync>(&mut self, value: T) {
152        let mut vec = self.get_mut::<T>();
153        vec.push(value);
154    }
155
156    /// Inserts a boxed value of any type into the `AnyMultiMap`.
157    pub fn insert_boxed(&mut self, value: AnyCloneBox) {
158        // Defer do the vtable dispatch to the boxed value, which will handle inserting itself into
159        // the multimap.
160        value.insert_into_multimap(self);
161    }
162}
163
164struct TypeCount(usize);
165
166impl fmt::Debug for TypeCount {
167    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168        f.write_fmt(format_args!("{} entries", self.0))
169    }
170}
171
172impl fmt::Debug for AnyMultiMap {
173    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174        f.debug_map()
175            .entries(
176                self.map
177                    .values()
178                    .map(|vec| (vec.type_name(), TypeCount(vec.len()))),
179            )
180            .finish()
181    }
182}