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
19 .downcast()
20 .map(|boxed| *boxed)
21 .map_err(|e| KvPair(key, e))
22 }
23}
24
25#[derive(Debug)]
27pub struct OccupiedEntry<'a, T> {
28 data: hash_map::OccupiedEntry<'a, TypeId, Box<dyn Any>>,
29 marker: PhantomData<fn(T)>,
30}
31
32impl<'a, T: 'static> OccupiedEntry<'a, T> {
33 pub fn get(&self) -> &T {
35 self.data.get().downcast_ref().unwrap()
36 }
37
38 pub fn get_mut(&mut self) -> &mut T {
40 self.data.get_mut().downcast_mut().unwrap()
41 }
42
43 pub fn into_mut(self) -> &'a mut T {
46 self.data.into_mut().downcast_mut().unwrap()
47 }
48
49 pub fn insert(&mut self, value: T) -> T {
51 self.data
52 .insert(Box::new(value))
53 .downcast()
54 .map(|boxed| *boxed)
55 .unwrap()
56 }
57
58 pub fn remove(self) -> T {
60 self.data.remove().downcast().map(|boxed| *boxed).unwrap()
61 }
62}
63
64#[derive(Debug)]
66pub struct VacantEntry<'a, T> {
67 data: hash_map::VacantEntry<'a, TypeId, Box<dyn Any>>,
68 marker: PhantomData<fn(T)>,
69}
70
71impl<'a, T: 'static> VacantEntry<'a, T> {
72 pub fn insert(self, value: T) -> &'a mut T {
74 self.data.insert(Box::new(value)).downcast_mut().unwrap()
75 }
76}
77
78#[derive(Debug)]
80pub enum Entry<'a, T> {
81 Occupied(OccupiedEntry<'a, T>),
82 Vacant(VacantEntry<'a, T>),
83}
84
85impl<'a, T: 'static> Entry<'a, T> {
86 pub fn or_insert(self, default: T) -> &'a mut T {
89 match self {
90 Entry::Occupied(inner) => inner.into_mut(),
91 Entry::Vacant(inner) => inner.insert(default),
92 }
93 }
94
95 pub fn or_insert_with<F: FnOnce() -> T>(self, default: F) -> &'a mut T {
98 match self {
99 Entry::Occupied(inner) => inner.into_mut(),
100 Entry::Vacant(inner) => inner.insert(default()),
101 }
102 }
103}
104
105#[derive(Debug, Default)]
106pub struct TypeMap {
108 map: Option<FxHashMap<TypeId, Box<dyn Any>>>,
109}
110
111impl TypeMap {
112 #[inline]
114 pub fn new() -> Self {
115 Self { map: None }
116 }
117
118 pub fn insert_kv_pair(&mut self, KvPair(key, value): KvPair) -> Option<KvPair> {
122 self.map
123 .get_or_insert_with(FxHashMap::default)
124 .insert(key, value)
125 .map(|old_value| KvPair(key, old_value))
126 }
127
128 pub fn insert<T: 'static>(&mut self, val: T) -> Option<T> {
132 self.map
133 .get_or_insert_with(FxHashMap::default)
134 .insert(TypeId::of::<T>(), Box::new(val))
135 .and_then(|boxed| boxed.downcast().ok().map(|boxed| *boxed))
136 }
137
138 pub fn contains<T: 'static>(&self) -> bool {
140 self.map
141 .as_ref()
142 .and_then(|m| m.get(&TypeId::of::<T>()))
143 .is_some()
144 }
145
146 pub fn get<T: 'static>(&self) -> Option<&T> {
148 self.map
149 .as_ref()
150 .and_then(|m| m.get(&TypeId::of::<T>()))
151 .and_then(|boxed| boxed.downcast_ref())
152 }
153
154 pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
156 self.map
157 .as_mut()
158 .and_then(|m| m.get_mut(&TypeId::of::<T>()))
159 .and_then(|boxed| boxed.downcast_mut())
160 }
161
162 pub fn remove<T: 'static>(&mut self) -> Option<T> {
166 self.map
167 .as_mut()
168 .and_then(|m| m.remove(&TypeId::of::<T>()))
169 .and_then(|boxed| boxed.downcast().ok().map(|boxed| *boxed))
170 }
171
172 #[inline]
174 pub fn clear(&mut self) {
175 self.map = None;
176 }
177
178 pub fn entry<T: 'static>(&mut self) -> Entry<T> {
180 match self
181 .map
182 .get_or_insert_with(FxHashMap::default)
183 .entry(TypeId::of::<T>())
184 {
185 hash_map::Entry::Occupied(e) => Entry::Occupied(OccupiedEntry {
186 data: e,
187 marker: PhantomData,
188 }),
189 hash_map::Entry::Vacant(e) => Entry::Vacant(VacantEntry {
190 data: e,
191 marker: PhantomData,
192 }),
193 }
194 }
195}
196
197pub mod concurrent {
199
200 use std::any::{Any, TypeId};
201
202 use rustc_hash::FxHashMap;
203
204 use std::collections::hash_map;
205 use std::marker::PhantomData;
206
207 pub struct KvPair(TypeId, Box<dyn Any + Send + Sync>);
209
210 impl KvPair {
211 pub fn new<T: 'static + Send + Sync>(value: T) -> Self {
212 KvPair(TypeId::of::<T>(), Box::new(value))
213 }
214
215 pub fn extract<T: 'static + Send + Sync>(self) -> Result<T, Self> {
216 let KvPair(key, value) = self;
217 if value.is::<T>() {
218 Ok((value as Box<dyn Any>)
219 .downcast()
220 .map(|boxed| *boxed)
221 .unwrap())
222 } else {
223 Err(KvPair(key, value))
224 }
225 }
226 }
227
228 #[derive(Debug)]
230 pub struct OccupiedEntry<'a, T> {
231 data: hash_map::OccupiedEntry<'a, TypeId, Box<dyn Any + Send + Sync>>,
232 marker: PhantomData<fn(T)>,
233 }
234
235 impl<'a, T: 'static + Send + Sync> OccupiedEntry<'a, T> {
236 pub fn get(&self) -> &T {
238 self.data.get().downcast_ref().unwrap()
239 }
240
241 pub fn get_mut(&mut self) -> &mut T {
243 self.data.get_mut().downcast_mut().unwrap()
244 }
245
246 pub fn into_mut(self) -> &'a mut T {
249 self.data.into_mut().downcast_mut().unwrap()
250 }
251
252 pub fn insert(&mut self, value: T) -> T {
254 (self.data.insert(Box::new(value)) as Box<dyn Any>)
255 .downcast()
256 .map(|boxed| *boxed)
257 .unwrap()
258 }
259
260 pub fn remove(self) -> T {
262 (self.data.remove() as Box<dyn Any>)
263 .downcast()
264 .map(|boxed| *boxed)
265 .unwrap()
266 }
267 }
268
269 #[derive(Debug)]
271 pub struct VacantEntry<'a, T> {
272 data: hash_map::VacantEntry<'a, TypeId, Box<dyn Any + Send + Sync>>,
273 marker: PhantomData<fn(T)>,
274 }
275
276 impl<'a, T: 'static + Send + Sync> VacantEntry<'a, T> {
277 pub fn insert(self, value: T) -> &'a mut T {
279 self.data.insert(Box::new(value)).downcast_mut().unwrap()
280 }
281 }
282
283 #[derive(Debug)]
285 pub enum Entry<'a, T> {
286 Occupied(OccupiedEntry<'a, T>),
287 Vacant(VacantEntry<'a, T>),
288 }
289
290 impl<'a, T: 'static + Send + Sync> Entry<'a, T> {
291 pub fn or_insert(self, default: T) -> &'a mut T {
294 match self {
295 Entry::Occupied(inner) => inner.into_mut(),
296 Entry::Vacant(inner) => inner.insert(default),
297 }
298 }
299
300 pub fn or_insert_with<F: FnOnce() -> T>(self, default: F) -> &'a mut T {
303 match self {
304 Entry::Occupied(inner) => inner.into_mut(),
305 Entry::Vacant(inner) => inner.insert(default()),
306 }
307 }
308 }
309
310 #[derive(Debug, Default)]
311 pub struct TypeMap {
313 map: Option<FxHashMap<TypeId, Box<dyn Any + Send + Sync>>>,
314 }
315
316 impl TypeMap {
317 #[inline]
319 pub fn new() -> Self {
320 Self { map: None }
321 }
322
323 pub fn insert_kv_pair(&mut self, KvPair(key, value): KvPair) -> Option<KvPair> {
327 self.map
328 .get_or_insert_with(FxHashMap::default)
329 .insert(key, value)
330 .map(|old_value| KvPair(key, old_value))
331 }
332
333 pub fn insert<T: Send + Sync + 'static>(&mut self, val: T) -> Option<T> {
337 self.map
338 .get_or_insert_with(FxHashMap::default)
339 .insert(TypeId::of::<T>(), Box::new(val))
340 .and_then(|boxed| (boxed as Box<dyn Any>).downcast().ok().map(|boxed| *boxed))
341 }
342
343 pub fn contains<T: 'static>(&self) -> bool {
345 self.map
346 .as_ref()
347 .and_then(|m| m.get(&TypeId::of::<T>()))
348 .is_some()
349 }
350
351 pub fn get<T: 'static>(&self) -> Option<&T> {
353 self.map
354 .as_ref()
355 .and_then(|m| m.get(&TypeId::of::<T>()))
356 .and_then(|boxed| boxed.downcast_ref())
357 }
358
359 pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
361 self.map
362 .as_mut()
363 .and_then(|m| m.get_mut(&TypeId::of::<T>()))
364 .and_then(|boxed| boxed.downcast_mut())
365 }
366
367 pub fn remove<T: 'static>(&mut self) -> Option<T> {
371 self.map
372 .as_mut()
373 .and_then(|m| m.remove(&TypeId::of::<T>()))
374 .and_then(|boxed| (boxed as Box<dyn Any>).downcast().ok().map(|boxed| *boxed))
375 }
376
377 #[inline]
379 pub fn clear(&mut self) {
380 self.map = None;
381 }
382
383 pub fn entry<T: 'static + Send + Sync>(&mut self) -> Entry<T> {
385 match self
386 .map
387 .get_or_insert_with(FxHashMap::default)
388 .entry(TypeId::of::<T>())
389 {
390 hash_map::Entry::Occupied(e) => Entry::Occupied(OccupiedEntry {
391 data: e,
392 marker: PhantomData,
393 }),
394 hash_map::Entry::Vacant(e) => Entry::Vacant(VacantEntry {
395 data: e,
396 marker: PhantomData,
397 }),
398 }
399 }
400 }
401}
402
403#[test]
404fn test_type_map() {
405 #[derive(Debug, PartialEq)]
406 struct MyType(i32);
407
408 #[derive(Debug, PartialEq, Default)]
409 struct MyType2(String);
410
411 let mut map = TypeMap::new();
412
413 map.insert(5i32);
414 map.insert(MyType(10));
415
416 assert_eq!(map.get(), Some(&5i32));
417 assert_eq!(map.get_mut(), Some(&mut 5i32));
418
419 assert_eq!(map.remove::<i32>(), Some(5i32));
420 assert!(map.get::<i32>().is_none());
421
422 assert_eq!(map.get::<bool>(), None);
423 assert_eq!(map.get(), Some(&MyType(10)));
424
425 let entry = map.entry::<MyType2>();
426
427 let v = entry.or_insert_with(MyType2::default);
428
429 v.0 = "Hello".into();
430
431 assert_eq!(map.get(), Some(&MyType2("Hello".into())));
432}