bevy_ecs/entity/
hash_map.rs

1//! Contains the [`EntityHashMap`] type, a [`HashMap`] pre-configured to use [`EntityHash`] hashing.
2//!
3//! This module is a lightweight wrapper around Bevy's [`HashMap`] that is more performant for [`Entity`] keys.
4
5use core::{
6    fmt::{self, Debug, Formatter},
7    iter::FusedIterator,
8    marker::PhantomData,
9    ops::{Deref, DerefMut, Index},
10};
11
12use bevy_platform::collections::hash_map::{self, HashMap};
13#[cfg(feature = "bevy_reflect")]
14use bevy_reflect::Reflect;
15
16use super::{Entity, EntityEquivalent, EntityHash, EntitySetIterator};
17
18/// A [`HashMap`] pre-configured to use [`EntityHash`] hashing.
19#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
20#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub struct EntityHashMap<V>(pub(crate) HashMap<Entity, V, EntityHash>);
23
24impl<V> EntityHashMap<V> {
25    /// Creates an empty `EntityHashMap`.
26    ///
27    /// Equivalent to [`HashMap::with_hasher(EntityHash)`].
28    ///
29    /// [`HashMap::with_hasher(EntityHash)`]: HashMap::with_hasher
30    pub const fn new() -> Self {
31        Self(HashMap::with_hasher(EntityHash))
32    }
33
34    /// Creates an empty `EntityHashMap` with the specified capacity.
35    ///
36    /// Equivalent to [`HashMap::with_capacity_and_hasher(n, EntityHash)`].
37    ///
38    /// [`HashMap:with_capacity_and_hasher(n, EntityHash)`]: HashMap::with_capacity_and_hasher
39    pub fn with_capacity(n: usize) -> Self {
40        Self(HashMap::with_capacity_and_hasher(n, EntityHash))
41    }
42
43    /// Returns the inner [`HashMap`].
44    pub fn into_inner(self) -> HashMap<Entity, V, EntityHash> {
45        self.0
46    }
47
48    /// An iterator visiting all keys in arbitrary order.
49    /// The iterator element type is `&'a Entity`.
50    ///
51    /// Equivalent to [`HashMap::keys`].
52    pub fn keys(&self) -> Keys<'_, V> {
53        Keys(self.0.keys(), PhantomData)
54    }
55
56    /// Creates a consuming iterator visiting all the keys in arbitrary order.
57    /// The map cannot be used after calling this.
58    /// The iterator element type is [`Entity`].
59    ///
60    /// Equivalent to [`HashMap::into_keys`].
61    pub fn into_keys(self) -> IntoKeys<V> {
62        IntoKeys(self.0.into_keys(), PhantomData)
63    }
64}
65
66impl<V> Default for EntityHashMap<V> {
67    fn default() -> Self {
68        Self(Default::default())
69    }
70}
71
72impl<V> Deref for EntityHashMap<V> {
73    type Target = HashMap<Entity, V, EntityHash>;
74
75    fn deref(&self) -> &Self::Target {
76        &self.0
77    }
78}
79
80impl<V> DerefMut for EntityHashMap<V> {
81    fn deref_mut(&mut self) -> &mut Self::Target {
82        &mut self.0
83    }
84}
85
86impl<'a, V: Copy> Extend<&'a (Entity, V)> for EntityHashMap<V> {
87    fn extend<T: IntoIterator<Item = &'a (Entity, V)>>(&mut self, iter: T) {
88        self.0.extend(iter);
89    }
90}
91
92impl<'a, V: Copy> Extend<(&'a Entity, &'a V)> for EntityHashMap<V> {
93    fn extend<T: IntoIterator<Item = (&'a Entity, &'a V)>>(&mut self, iter: T) {
94        self.0.extend(iter);
95    }
96}
97
98impl<V> Extend<(Entity, V)> for EntityHashMap<V> {
99    fn extend<T: IntoIterator<Item = (Entity, V)>>(&mut self, iter: T) {
100        self.0.extend(iter);
101    }
102}
103
104impl<V, const N: usize> From<[(Entity, V); N]> for EntityHashMap<V> {
105    fn from(value: [(Entity, V); N]) -> Self {
106        Self(HashMap::from_iter(value))
107    }
108}
109
110impl<V> FromIterator<(Entity, V)> for EntityHashMap<V> {
111    fn from_iter<I: IntoIterator<Item = (Entity, V)>>(iterable: I) -> Self {
112        Self(HashMap::from_iter(iterable))
113    }
114}
115
116impl<V, Q: EntityEquivalent + ?Sized> Index<&Q> for EntityHashMap<V> {
117    type Output = V;
118    fn index(&self, key: &Q) -> &V {
119        self.0.index(&key.entity())
120    }
121}
122
123impl<'a, V> IntoIterator for &'a EntityHashMap<V> {
124    type Item = (&'a Entity, &'a V);
125    type IntoIter = hash_map::Iter<'a, Entity, V>;
126
127    fn into_iter(self) -> Self::IntoIter {
128        self.0.iter()
129    }
130}
131
132impl<'a, V> IntoIterator for &'a mut EntityHashMap<V> {
133    type Item = (&'a Entity, &'a mut V);
134    type IntoIter = hash_map::IterMut<'a, Entity, V>;
135
136    fn into_iter(self) -> Self::IntoIter {
137        self.0.iter_mut()
138    }
139}
140
141impl<V> IntoIterator for EntityHashMap<V> {
142    type Item = (Entity, V);
143    type IntoIter = hash_map::IntoIter<Entity, V>;
144
145    fn into_iter(self) -> Self::IntoIter {
146        self.0.into_iter()
147    }
148}
149
150/// An iterator over the keys of a [`EntityHashMap`] in arbitrary order.
151/// The iterator element type is `&'a Entity`.
152///
153/// This struct is created by the [`keys`] method on [`EntityHashMap`]. See its documentation for more.
154///
155/// [`keys`]: EntityHashMap::keys
156pub struct Keys<'a, V, S = EntityHash>(hash_map::Keys<'a, Entity, V>, PhantomData<S>);
157
158impl<'a, V> Keys<'a, V> {
159    /// Returns the inner [`Keys`](hash_map::Keys).
160    pub fn into_inner(self) -> hash_map::Keys<'a, Entity, V> {
161        self.0
162    }
163}
164
165impl<'a, V> Deref for Keys<'a, V> {
166    type Target = hash_map::Keys<'a, Entity, V>;
167
168    fn deref(&self) -> &Self::Target {
169        &self.0
170    }
171}
172
173impl<'a, V> Iterator for Keys<'a, V> {
174    type Item = &'a Entity;
175
176    fn next(&mut self) -> Option<Self::Item> {
177        self.0.next()
178    }
179}
180
181impl<V> ExactSizeIterator for Keys<'_, V> {}
182
183impl<V> FusedIterator for Keys<'_, V> {}
184
185impl<V> Clone for Keys<'_, V> {
186    fn clone(&self) -> Self {
187        Self(self.0.clone(), PhantomData)
188    }
189}
190
191impl<V: Debug> Debug for Keys<'_, V> {
192    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
193        f.debug_tuple("Keys").field(&self.0).field(&self.1).finish()
194    }
195}
196
197impl<V> Default for Keys<'_, V> {
198    fn default() -> Self {
199        Self(Default::default(), PhantomData)
200    }
201}
202
203// SAFETY: Keys stems from a correctly behaving `HashMap<Entity, V, EntityHash>`.
204unsafe impl<V> EntitySetIterator for Keys<'_, V> {}
205
206/// An owning iterator over the keys of a [`EntityHashMap`] in arbitrary order.
207/// The iterator element type is [`Entity`].
208///
209/// This struct is created by the [`into_keys`] method on [`EntityHashMap`].
210/// See its documentation for more.
211/// The map cannot be used after calling that method.
212///
213/// [`into_keys`]: EntityHashMap::into_keys
214pub struct IntoKeys<V, S = EntityHash>(hash_map::IntoKeys<Entity, V>, PhantomData<S>);
215
216impl<V> IntoKeys<V> {
217    /// Returns the inner [`IntoKeys`](hash_map::IntoKeys).
218    pub fn into_inner(self) -> hash_map::IntoKeys<Entity, V> {
219        self.0
220    }
221}
222
223impl<V> Deref for IntoKeys<V> {
224    type Target = hash_map::IntoKeys<Entity, V>;
225
226    fn deref(&self) -> &Self::Target {
227        &self.0
228    }
229}
230
231impl<V> Iterator for IntoKeys<V> {
232    type Item = Entity;
233
234    fn next(&mut self) -> Option<Self::Item> {
235        self.0.next()
236    }
237}
238
239impl<V> ExactSizeIterator for IntoKeys<V> {}
240
241impl<V> FusedIterator for IntoKeys<V> {}
242
243impl<V: Debug> Debug for IntoKeys<V> {
244    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
245        f.debug_tuple("IntoKeys")
246            .field(&self.0)
247            .field(&self.1)
248            .finish()
249    }
250}
251
252impl<V> Default for IntoKeys<V> {
253    fn default() -> Self {
254        Self(Default::default(), PhantomData)
255    }
256}
257
258// SAFETY: IntoKeys stems from a correctly behaving `HashMap<Entity, V, EntityHash>`.
259unsafe impl<V> EntitySetIterator for IntoKeys<V> {}
260
261#[cfg(test)]
262mod tests {
263    use super::*;
264    use bevy_reflect::Reflect;
265    use static_assertions::assert_impl_all;
266
267    // Check that the HashMaps are Clone if the key/values are Clone
268    assert_impl_all!(EntityHashMap::<usize>: Clone);
269    // EntityHashMap should implement Reflect
270    #[cfg(feature = "bevy_reflect")]
271    assert_impl_all!(EntityHashMap::<i32>: Reflect);
272}