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}