|
1 | 1 | use core::{any::TypeId, hash::Hash};
|
2 | 2 |
|
3 | 3 | use bevy_platform::{
|
4 |
| - collections::HashMap, |
| 4 | + collections::{hash_map::Entry, HashMap}, |
5 | 5 | hash::{Hashed, NoOpHash, PassHash},
|
6 | 6 | };
|
7 | 7 |
|
@@ -38,6 +38,78 @@ impl<K: Hash + Eq + PartialEq + Clone, V> PreHashMapExt<K, V> for PreHashMap<K,
|
38 | 38 | /// Iteration order only depends on the order of insertions and deletions.
|
39 | 39 | pub type TypeIdMap<V> = HashMap<TypeId, V, NoOpHash>;
|
40 | 40 |
|
| 41 | +/// Extension trait to make use of [`TypeIdMap`] more ergonomic. |
| 42 | +/// |
| 43 | +/// Each function on this trait is a trivial wrapper for a function |
| 44 | +/// on [`HashMap`], replacing a `TypeId` key with a |
| 45 | +/// generic parameter `T`. |
| 46 | +/// |
| 47 | +/// # Examples |
| 48 | +/// |
| 49 | +/// ```rust |
| 50 | +/// # use std::any::TypeId; |
| 51 | +/// # use bevy_utils::TypeIdMap; |
| 52 | +/// use bevy_utils::TypeIdMapExt; |
| 53 | +/// |
| 54 | +/// struct MyType; |
| 55 | +/// |
| 56 | +/// // Using the built-in `HashMap` functions requires manually looking up `TypeId`s. |
| 57 | +/// let mut map = TypeIdMap::default(); |
| 58 | +/// map.insert(TypeId::of::<MyType>(), 7); |
| 59 | +/// assert_eq!(map.get(&TypeId::of::<MyType>()), Some(&7)); |
| 60 | +/// |
| 61 | +/// // Using `TypeIdMapExt` functions does the lookup for you. |
| 62 | +/// map.insert_type::<MyType>(7); |
| 63 | +/// assert_eq!(map.get_type::<MyType>(), Some(&7)); |
| 64 | +/// ``` |
| 65 | +pub trait TypeIdMapExt<V> { |
| 66 | + /// Inserts a value for the type `T`. |
| 67 | + /// |
| 68 | + /// If the map did not previously contain this key then [`None`] is returned, |
| 69 | + /// otherwise the value for this key is updated and the old value returned. |
| 70 | + fn insert_type<T: ?Sized + 'static>(&mut self, v: V) -> Option<V>; |
| 71 | + |
| 72 | + /// Returns a reference to the value for type `T`, if one exists. |
| 73 | + fn get_type<T: ?Sized + 'static>(&self) -> Option<&V>; |
| 74 | + |
| 75 | + /// Returns a mutable reference to the value for type `T`, if one exists. |
| 76 | + fn get_type_mut<T: ?Sized + 'static>(&mut self) -> Option<&mut V>; |
| 77 | + |
| 78 | + /// Removes type `T` from the map, returning the value for this |
| 79 | + /// key if it was previously present. |
| 80 | + fn remove_type<T: ?Sized + 'static>(&mut self) -> Option<V>; |
| 81 | + |
| 82 | + /// Gets the type `T`'s entry in the map for in-place manipulation. |
| 83 | + fn entry_type<T: ?Sized + 'static>(&mut self) -> Entry<'_, TypeId, V, NoOpHash>; |
| 84 | +} |
| 85 | + |
| 86 | +impl<V> TypeIdMapExt<V> for TypeIdMap<V> { |
| 87 | + #[inline] |
| 88 | + fn insert_type<T: ?Sized + 'static>(&mut self, v: V) -> Option<V> { |
| 89 | + self.insert(TypeId::of::<T>(), v) |
| 90 | + } |
| 91 | + |
| 92 | + #[inline] |
| 93 | + fn get_type<T: ?Sized + 'static>(&self) -> Option<&V> { |
| 94 | + self.get(&TypeId::of::<T>()) |
| 95 | + } |
| 96 | + |
| 97 | + #[inline] |
| 98 | + fn get_type_mut<T: ?Sized + 'static>(&mut self) -> Option<&mut V> { |
| 99 | + self.get_mut(&TypeId::of::<T>()) |
| 100 | + } |
| 101 | + |
| 102 | + #[inline] |
| 103 | + fn remove_type<T: ?Sized + 'static>(&mut self) -> Option<V> { |
| 104 | + self.remove(&TypeId::of::<T>()) |
| 105 | + } |
| 106 | + |
| 107 | + #[inline] |
| 108 | + fn entry_type<T: ?Sized + 'static>(&mut self) -> Entry<'_, TypeId, V, NoOpHash> { |
| 109 | + self.entry(TypeId::of::<T>()) |
| 110 | + } |
| 111 | +} |
| 112 | + |
41 | 113 | #[cfg(test)]
|
42 | 114 | mod tests {
|
43 | 115 | use super::*;
|
@@ -67,7 +139,7 @@ mod tests {
|
67 | 139 | #[test]
|
68 | 140 | fn stable_hash_within_same_program_execution() {
|
69 | 141 | use alloc::vec::Vec;
|
70 |
| - |
| 142 | + |
71 | 143 | let mut map_1 = <HashMap<_, _>>::default();
|
72 | 144 | let mut map_2 = <HashMap<_, _>>::default();
|
73 | 145 | for i in 1..10 {
|
|
0 commit comments