1use std::any::{Any, TypeId};
2
3use rustc_hash::FxHashMap;
4
5use std::collections::hash_map;
6use std::marker::PhantomData;
7
8pub struct KvPair(TypeId, Box<dyn Any>);
10
11impl KvPair {
12 pub fn new<T: 'static>(value: T) -> Self {
13 KvPair(TypeId::of::<T>(), Box::new(value))
14 }
15
16 pub fn extract<T: 'static>(self) -> Result<T, Self> {
17 let KvPair(key, value) = self;
18 value.downcast().map(|boxed| *boxed).map_err(|e| KvPair(key, e))
19 }
20}
21
22#[derive(Debug)]
24pub struct OccupiedEntry<'a, T> {
25 data: hash_map::OccupiedEntry<'a, TypeId, Box<dyn Any>>,
26 marker: PhantomData<fn(T)>,
27}
28
29impl<'a, T: 'static> OccupiedEntry<'a, T> {
30 pub fn get(&self) -> &T {
32 self.data.get().downcast_ref().unwrap()
33 }
34
35 pub fn get_mut(&mut self) -> &mut T {
37 self.data.get_mut().downcast_mut().unwrap()
38 }
39
40 pub fn into_mut(self) -> &'a mut T {
43 self.data.into_mut().downcast_mut().unwrap()
44 }
45
46 pub fn insert(&mut self, value: T) -> T {
48 self.data.insert(Box::new(value)).downcast().map(|boxed| *boxed).unwrap()
49 }
50
51 pub fn remove(self) -> T {
53 self.data.remove().downcast().map(|boxed| *boxed).unwrap()
54 }
55}
56
57#[derive(Debug)]
59pub struct VacantEntry<'a, T> {
60 data: hash_map::VacantEntry<'a, TypeId, Box<dyn Any>>,
61 marker: PhantomData<fn(T)>,
62}
63
64impl<'a, T: 'static> VacantEntry<'a, T> {
65 pub fn insert(self, value: T) -> &'a mut T {
67 self.data.insert(Box::new(value)).downcast_mut().unwrap()
68 }
69}
70
71#[derive(Debug)]
73pub enum Entry<'a, T> {
74 Occupied(OccupiedEntry<'a, T>),
75 Vacant(VacantEntry<'a, T>),
76}
77
78impl<'a, T: 'static> Entry<'a, T> {
79 pub fn or_insert(self, default: T) -> &'a mut T {
82 match self {
83 Entry::Occupied(inner) => inner.into_mut(),
84 Entry::Vacant(inner) => inner.insert(default),
85 }
86 }
87
88 pub fn or_insert_with<F: FnOnce() -> T>(self, default: F) -> &'a mut T {
91 match self {
92 Entry::Occupied(inner) => inner.into_mut(),
93 Entry::Vacant(inner) => inner.insert(default()),
94 }
95 }
96}
97
98#[derive(Debug, Default)]
99pub struct TypeMap {
101 map: Option<FxHashMap<TypeId, Box<dyn Any>>>,
102}
103
104impl TypeMap {
105 #[inline]
107 pub fn new() -> Self {
108 Self { map: None }
109 }
110
111 pub fn insert_kv_pair(&mut self, KvPair(key, value): KvPair) -> Option<KvPair> {
115 self.map
116 .get_or_insert_with(|| FxHashMap::default())
117 .insert(key, value)
118 .map(|old_value| KvPair(key, old_value))
119 }
120
121 pub fn insert<T: 'static>(&mut self, val: T) -> Option<T> {
125 self.map
126 .get_or_insert_with(|| FxHashMap::default())
127 .insert(TypeId::of::<T>(), Box::new(val))
128 .and_then(|boxed| boxed.downcast().ok().map(|boxed| *boxed))
129 }
130
131 pub fn contains<T: 'static>(&self) -> bool {
133 self.map.as_ref().and_then(|m| m.get(&TypeId::of::<T>())).is_some()
134 }
135
136 pub fn get<T: 'static>(&self) -> Option<&T> {
138 self.map
139 .as_ref()
140 .and_then(|m| m.get(&TypeId::of::<T>()))
141 .and_then(|boxed| boxed.downcast_ref())
142 }
143
144 pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
146 self.map
147 .as_mut()
148 .and_then(|m| m.get_mut(&TypeId::of::<T>()))
149 .and_then(|boxed| boxed.downcast_mut())
150 }
151
152 pub fn remove<T: 'static>(&mut self) -> Option<T> {
156 self.map
157 .as_mut()
158 .and_then(|m| m.remove(&TypeId::of::<T>()))
159 .and_then(|boxed| boxed.downcast().ok().map(|boxed| *boxed))
160 }
161
162 #[inline]
164 pub fn clear(&mut self) {
165 self.map = None;
166 }
167
168 pub fn entry<T: 'static>(&mut self) -> Entry<T> {
170 match self.map.get_or_insert_with(|| FxHashMap::default()).entry(TypeId::of::<T>()) {
171 hash_map::Entry::Occupied(e) => {
172 Entry::Occupied(OccupiedEntry { data: e, marker: PhantomData })
173 }
174 hash_map::Entry::Vacant(e) => {
175 Entry::Vacant(VacantEntry { data: e, marker: PhantomData })
176 }
177 }
178 }
179}
180
181pub mod concurrent {
183
184 use std::any::{Any, TypeId};
185
186 use rustc_hash::FxHashMap;
187
188 use std::collections::hash_map;
189 use std::marker::PhantomData;
190
191 pub struct KvPair(TypeId, Box<dyn Any + Send + Sync>);
193
194 impl KvPair {
195 pub fn new<T: 'static + Send + Sync>(value: T) -> Self {
196 KvPair(TypeId::of::<T>(), Box::new(value))
197 }
198
199 pub fn extract<T: 'static + Send + Sync>(self) -> Result<T, Self> {
200 let KvPair(key, value) = self;
201 if value.is::<T>() {
202 Ok((value as Box<dyn Any>).downcast().map(|boxed| *boxed).unwrap())
203 } else {
204 Err(KvPair(key, value))
205 }
206 }
207 }
208
209 #[derive(Debug)]
211 pub struct OccupiedEntry<'a, T> {
212 data: hash_map::OccupiedEntry<'a, TypeId, Box<dyn Any + Send + Sync>>,
213 marker: PhantomData<fn(T)>,
214 }
215
216 impl<'a, T: 'static + Send + Sync> OccupiedEntry<'a, T> {
217 pub fn get(&self) -> &T {
219 self.data.get().downcast_ref().unwrap()
220 }
221
222 pub fn get_mut(&mut self) -> &mut T {
224 self.data.get_mut().downcast_mut().unwrap()
225 }
226
227 pub fn into_mut(self) -> &'a mut T {
230 self.data.into_mut().downcast_mut().unwrap()
231 }
232
233 pub fn insert(&mut self, value: T) -> T {
235 (self.data.insert(Box::new(value)) as Box<dyn Any>)
236 .downcast()
237 .map(|boxed| *boxed)
238 .unwrap()
239 }
240
241 pub fn remove(self) -> T {
243 (self.data.remove() as Box<dyn Any>).downcast().map(|boxed| *boxed).unwrap()
244 }
245 }
246
247 #[derive(Debug)]
249 pub struct VacantEntry<'a, T> {
250 data: hash_map::VacantEntry<'a, TypeId, Box<dyn Any + Send + Sync>>,
251 marker: PhantomData<fn(T)>,
252 }
253
254 impl<'a, T: 'static + Send + Sync> VacantEntry<'a, T> {
255 pub fn insert(self, value: T) -> &'a mut T {
257 self.data.insert(Box::new(value)).downcast_mut().unwrap()
258 }
259 }
260
261 #[derive(Debug)]
263 pub enum Entry<'a, T> {
264 Occupied(OccupiedEntry<'a, T>),
265 Vacant(VacantEntry<'a, T>),
266 }
267
268 impl<'a, T: 'static + Send + Sync> Entry<'a, T> {
269 pub fn or_insert(self, default: T) -> &'a mut T {
272 match self {
273 Entry::Occupied(inner) => inner.into_mut(),
274 Entry::Vacant(inner) => inner.insert(default),
275 }
276 }
277
278 pub fn or_insert_with<F: FnOnce() -> T>(self, default: F) -> &'a mut T {
281 match self {
282 Entry::Occupied(inner) => inner.into_mut(),
283 Entry::Vacant(inner) => inner.insert(default()),
284 }
285 }
286 }
287
288 #[derive(Debug, Default)]
289 pub struct TypeMap {
291 map: Option<FxHashMap<TypeId, Box<dyn Any + Send + Sync>>>,
292 }
293
294 impl TypeMap {
295 #[inline]
297 pub fn new() -> Self {
298 Self { map: None }
299 }
300
301 pub fn insert_kv_pair(&mut self, KvPair(key, value): KvPair) -> Option<KvPair> {
305 self.map
306 .get_or_insert_with(|| FxHashMap::default())
307 .insert(key, value)
308 .map(|old_value| KvPair(key, old_value))
309 }
310
311 pub fn insert<T: Send + Sync + 'static>(&mut self, val: T) -> Option<T> {
315 self.map
316 .get_or_insert_with(|| FxHashMap::default())
317 .insert(TypeId::of::<T>(), Box::new(val))
318 .and_then(|boxed| (boxed as Box<dyn Any>).downcast().ok().map(|boxed| *boxed))
319 }
320
321 pub fn contains<T: 'static>(&self) -> bool {
323 self.map.as_ref().and_then(|m| m.get(&TypeId::of::<T>())).is_some()
324 }
325
326 pub fn get<T: 'static>(&self) -> Option<&T> {
328 self.map
329 .as_ref()
330 .and_then(|m| m.get(&TypeId::of::<T>()))
331 .and_then(|boxed| boxed.downcast_ref())
332 }
333
334 pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
336 self.map
337 .as_mut()
338 .and_then(|m| m.get_mut(&TypeId::of::<T>()))
339 .and_then(|boxed| boxed.downcast_mut())
340 }
341
342 pub fn remove<T: 'static>(&mut self) -> Option<T> {
346 self.map
347 .as_mut()
348 .and_then(|m| m.remove(&TypeId::of::<T>()))
349 .and_then(|boxed| (boxed as Box<dyn Any>).downcast().ok().map(|boxed| *boxed))
350 }
351
352 #[inline]
354 pub fn clear(&mut self) {
355 self.map = None;
356 }
357
358 pub fn entry<T: 'static + Send + Sync>(&mut self) -> Entry<T> {
360 match self.map.get_or_insert_with(|| FxHashMap::default()).entry(TypeId::of::<T>()) {
361 hash_map::Entry::Occupied(e) => {
362 Entry::Occupied(OccupiedEntry { data: e, marker: PhantomData })
363 }
364 hash_map::Entry::Vacant(e) => {
365 Entry::Vacant(VacantEntry { data: e, marker: PhantomData })
366 }
367 }
368 }
369 }
370}
371
372#[test]
373fn test_type_map() {
374 #[derive(Debug, PartialEq)]
375 struct MyType(i32);
376
377 #[derive(Debug, PartialEq, Default)]
378 struct MyType2(String);
379
380 let mut map = TypeMap::new();
381
382 map.insert(5i32);
383 map.insert(MyType(10));
384
385 assert_eq!(map.get(), Some(&5i32));
386 assert_eq!(map.get_mut(), Some(&mut 5i32));
387
388 assert_eq!(map.remove::<i32>(), Some(5i32));
389 assert!(map.get::<i32>().is_none());
390
391 assert_eq!(map.get::<bool>(), None);
392 assert_eq!(map.get(), Some(&MyType(10)));
393
394 let entry = map.entry::<MyType2>();
395
396 let mut v = entry.or_insert_with(MyType2::default);
397
398 v.0 = "Hello".into();
399
400 assert_eq!(map.get(), Some(&MyType2("Hello".into())));
401}