make EntityHashMap and EntityHashSet proper types (#16912)
# Objective `EntityHashMap` and `EntityHashSet` iterators do not implement `EntitySetIterator`. ## Solution Make them newtypes instead of aliases. The methods that create the iterators can then produce their own newtypes that carry the `Hasher` generic and implement `EntitySetIterator`. Functionality remains the same otherwise. There are some other small benefits, f.e. the removal of `with_hasher` associated functions, and the ability to implement more traits ourselves. `MainEntityHashMap` and `MainEntityHashSet` are currently left as the previous type aliases, because supporting general `TrustedEntityBorrow` hashing is more complex. However, it can also be done. ## Testing Pre-existing `EntityHashMap` tests. ## Migration Guide Users of `with_hasher` and `with_capacity_and_hasher` on `EntityHashMap`/`Set` must now use `new` and `with_capacity` respectively. If the non-newtyped versions are required, they can be obtained via `Deref`, `DerefMut` or `into_inner` calls.
This commit is contained in:
parent
65835f5354
commit
8ac90ac542
@ -2,12 +2,9 @@ use core::hash::{BuildHasher, Hasher};
|
||||
|
||||
#[cfg(feature = "bevy_reflect")]
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_utils::hashbrown;
|
||||
|
||||
use super::Entity;
|
||||
|
||||
/// A [`BuildHasher`] that results in a [`EntityHasher`].
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Debug, Default, Clone)]
|
||||
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
|
||||
pub struct EntityHash;
|
||||
|
||||
@ -20,7 +17,7 @@ impl BuildHasher for EntityHash {
|
||||
}
|
||||
|
||||
/// A very fast hash that is only designed to work on generational indices
|
||||
/// like [`Entity`]. It will panic if attempting to hash a type containing
|
||||
/// like [`Entity`](super::Entity). It will panic if attempting to hash a type containing
|
||||
/// non-u64 fields.
|
||||
///
|
||||
/// This is heavily optimized for typical cases, where you have mostly live
|
||||
@ -78,21 +75,3 @@ impl Hasher for EntityHasher {
|
||||
self.hash = bits.wrapping_mul(UPPER_PHI);
|
||||
}
|
||||
}
|
||||
|
||||
/// A [`HashMap`](hashbrown::HashMap) pre-configured to use [`EntityHash`] hashing.
|
||||
pub type EntityHashMap<V> = hashbrown::HashMap<Entity, V, EntityHash>;
|
||||
|
||||
/// A [`HashSet`](hashbrown::HashSet) pre-configured to use [`EntityHash`] hashing.
|
||||
pub type EntityHashSet = hashbrown::HashSet<Entity, EntityHash>;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use static_assertions::assert_impl_all;
|
||||
|
||||
// Check that the HashMaps are Clone if the key/values are Clone
|
||||
assert_impl_all!(EntityHashMap::<usize>: Clone);
|
||||
// EntityHashMap should implement Reflect
|
||||
#[cfg(feature = "bevy_reflect")]
|
||||
assert_impl_all!(EntityHashMap::<i32>: Reflect);
|
||||
}
|
||||
|
279
crates/bevy_ecs/src/entity/hash_map.rs
Normal file
279
crates/bevy_ecs/src/entity/hash_map.rs
Normal file
@ -0,0 +1,279 @@
|
||||
use core::{
|
||||
fmt::{self, Debug, Formatter},
|
||||
iter::FusedIterator,
|
||||
marker::PhantomData,
|
||||
ops::{Deref, DerefMut, Index},
|
||||
};
|
||||
|
||||
#[cfg(feature = "bevy_reflect")]
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_utils::hashbrown::hash_map::{self, HashMap};
|
||||
|
||||
use super::{Entity, EntityHash, EntitySetIterator, TrustedEntityBorrow};
|
||||
|
||||
/// A [`HashMap`] pre-configured to use [`EntityHash`] hashing.
|
||||
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct EntityHashMap<V>(pub(crate) HashMap<Entity, V, EntityHash>);
|
||||
|
||||
impl<V> EntityHashMap<V> {
|
||||
/// Creates an empty `EntityHashMap`.
|
||||
///
|
||||
/// Equivalent to [`HashMap::with_hasher(EntityHash)`].
|
||||
///
|
||||
/// [`HashMap::with_hasher(EntityHash)`]: HashMap::with_hasher
|
||||
pub fn new() -> Self {
|
||||
Self(HashMap::with_hasher(EntityHash))
|
||||
}
|
||||
|
||||
/// Creates an empty `EntityHashMap` with the specified capacity.
|
||||
///
|
||||
/// Equivalent to [`HashMap::with_capacity_and_hasher(n, EntityHash)`].
|
||||
///
|
||||
/// [`HashMap:with_capacity_and_hasher(n, EntityHash)`]: HashMap::with_capacity_and_hasher
|
||||
pub fn with_capacity(n: usize) -> Self {
|
||||
Self(HashMap::with_capacity_and_hasher(n, EntityHash))
|
||||
}
|
||||
|
||||
/// Returns the inner [`HashMap`].
|
||||
pub fn into_inner(self) -> HashMap<Entity, V, EntityHash> {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// An iterator visiting all keys in arbitrary order.
|
||||
/// The iterator element type is `&'a Entity`.
|
||||
///
|
||||
/// Equivalent to [`HashMap::keys`].
|
||||
pub fn keys(&self) -> Keys<'_, V> {
|
||||
Keys(self.0.keys(), PhantomData)
|
||||
}
|
||||
|
||||
/// Creates a consuming iterator visiting all the keys in arbitrary order.
|
||||
/// The map cannot be used after calling this.
|
||||
/// The iterator element type is [`Entity`].
|
||||
///
|
||||
/// Equivalent to [`HashMap::into_keys`].
|
||||
pub fn into_keys(self) -> IntoKeys<V> {
|
||||
IntoKeys(self.0.into_keys(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Default for EntityHashMap<V> {
|
||||
fn default() -> Self {
|
||||
Self(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Deref for EntityHashMap<V> {
|
||||
type Target = HashMap<Entity, V, EntityHash>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> DerefMut for EntityHashMap<V> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V: Copy> Extend<&'a (Entity, V)> for EntityHashMap<V> {
|
||||
fn extend<T: IntoIterator<Item = &'a (Entity, V)>>(&mut self, iter: T) {
|
||||
self.0.extend(iter);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V: Copy> Extend<(&'a Entity, &'a V)> for EntityHashMap<V> {
|
||||
fn extend<T: IntoIterator<Item = (&'a Entity, &'a V)>>(&mut self, iter: T) {
|
||||
self.0.extend(iter);
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Extend<(Entity, V)> for EntityHashMap<V> {
|
||||
fn extend<T: IntoIterator<Item = (Entity, V)>>(&mut self, iter: T) {
|
||||
self.0.extend(iter);
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, const N: usize> From<[(Entity, V); N]> for EntityHashMap<V> {
|
||||
fn from(value: [(Entity, V); N]) -> Self {
|
||||
Self(HashMap::from_iter(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> FromIterator<(Entity, V)> for EntityHashMap<V> {
|
||||
fn from_iter<I: IntoIterator<Item = (Entity, V)>>(iterable: I) -> Self {
|
||||
Self(HashMap::from_iter(iterable))
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, Q: TrustedEntityBorrow + ?Sized> Index<&Q> for EntityHashMap<V> {
|
||||
type Output = V;
|
||||
fn index(&self, key: &Q) -> &V {
|
||||
self.0.index(&key.entity())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V> IntoIterator for &'a EntityHashMap<V> {
|
||||
type Item = (&'a Entity, &'a V);
|
||||
type IntoIter = hash_map::Iter<'a, Entity, V>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V> IntoIterator for &'a mut EntityHashMap<V> {
|
||||
type Item = (&'a Entity, &'a mut V);
|
||||
type IntoIter = hash_map::IterMut<'a, Entity, V>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IntoIterator for EntityHashMap<V> {
|
||||
type Item = (Entity, V);
|
||||
type IntoIter = hash_map::IntoIter<Entity, V>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the keys of a [`EntityHashMap`] in arbitrary order.
|
||||
/// The iterator element type is `&'a Entity`.
|
||||
///
|
||||
/// /// This struct is created by the [`keys`] method on [`EntityHashMap`]. See its documentation for more.
|
||||
///
|
||||
/// [`keys`]: EntityHashMap::keys
|
||||
pub struct Keys<'a, V, S = EntityHash>(hash_map::Keys<'a, Entity, V>, PhantomData<S>);
|
||||
|
||||
impl<'a, V> Keys<'a, V> {
|
||||
/// Returns the inner [`Keys`](hash_map::Keys).
|
||||
pub fn into_inner(self) -> hash_map::Keys<'a, Entity, V> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V> Deref for Keys<'a, V> {
|
||||
type Target = hash_map::Keys<'a, Entity, V>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> DerefMut for Keys<'_, V> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V> Iterator for Keys<'a, V> {
|
||||
type Item = &'a Entity;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.0.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> ExactSizeIterator for Keys<'_, V> {}
|
||||
|
||||
impl<V> FusedIterator for Keys<'_, V> {}
|
||||
|
||||
impl<V> Clone for Keys<'_, V> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Debug> Debug for Keys<'_, V> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Keys").field(&self.0).field(&self.1).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Default for Keys<'_, V> {
|
||||
fn default() -> Self {
|
||||
Self(Default::default(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: Keys stems from a correctly behaving `HashMap<Entity, V, EntityHash>`.
|
||||
unsafe impl<V> EntitySetIterator for Keys<'_, V> {}
|
||||
|
||||
/// An owning iterator over the keys of a [`EntityHashMap`] in arbitrary order.
|
||||
/// The iterator element type is [`Entity`].
|
||||
///
|
||||
/// This struct is created by the [`into_keys`] method on [`EntityHashMap`].
|
||||
/// See its documentation for more.
|
||||
/// The map cannot be used after calling that method.
|
||||
///
|
||||
/// [`into_keys`]: EntityHashMap::into_keys
|
||||
pub struct IntoKeys<V, S = EntityHash>(hash_map::IntoKeys<Entity, V>, PhantomData<S>);
|
||||
|
||||
impl<V> IntoKeys<V> {
|
||||
/// Returns the inner [`IntoKeys`](hash_map::IntoKeys).
|
||||
pub fn into_inner(self) -> hash_map::IntoKeys<Entity, V> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Deref for IntoKeys<V> {
|
||||
type Target = hash_map::IntoKeys<Entity, V>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> DerefMut for IntoKeys<V> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Iterator for IntoKeys<V> {
|
||||
type Item = Entity;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.0.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> ExactSizeIterator for IntoKeys<V> {}
|
||||
|
||||
impl<V> FusedIterator for IntoKeys<V> {}
|
||||
|
||||
impl<V: Debug> Debug for IntoKeys<V> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("IntoKeys")
|
||||
.field(&self.0)
|
||||
.field(&self.1)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Default for IntoKeys<V> {
|
||||
fn default() -> Self {
|
||||
Self(Default::default(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: IntoKeys stems from a correctly behaving `HashMap<Entity, V, EntityHash>`.
|
||||
unsafe impl<V> EntitySetIterator for IntoKeys<V> {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use bevy_reflect::Reflect;
|
||||
use static_assertions::assert_impl_all;
|
||||
|
||||
// Check that the HashMaps are Clone if the key/values are Clone
|
||||
assert_impl_all!(EntityHashMap::<usize>: Clone);
|
||||
// EntityHashMap should implement Reflect
|
||||
#[cfg(feature = "bevy_reflect")]
|
||||
assert_impl_all!(EntityHashMap::<i32>: Reflect);
|
||||
}
|
415
crates/bevy_ecs/src/entity/hash_set.rs
Normal file
415
crates/bevy_ecs/src/entity/hash_set.rs
Normal file
@ -0,0 +1,415 @@
|
||||
use core::{
|
||||
fmt::{self, Debug, Formatter},
|
||||
iter::FusedIterator,
|
||||
marker::PhantomData,
|
||||
ops::{
|
||||
BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Deref, DerefMut, Sub,
|
||||
SubAssign,
|
||||
},
|
||||
};
|
||||
|
||||
#[cfg(feature = "bevy_reflect")]
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_utils::hashbrown::hash_set::{self, HashSet};
|
||||
|
||||
use super::{Entity, EntityHash, EntitySetIterator};
|
||||
|
||||
/// A [`HashSet`] pre-configured to use [`EntityHash`] hashing.
|
||||
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
||||
pub struct EntityHashSet(pub(crate) HashSet<Entity, EntityHash>);
|
||||
|
||||
impl EntityHashSet {
|
||||
/// Creates an empty `EntityHashSet`.
|
||||
///
|
||||
/// Equivalent to [`HashSet::with_hasher(EntityHash)`].
|
||||
///
|
||||
/// [`HashSet::with_hasher(EntityHash)`]: HashSet::with_hasher
|
||||
pub fn new() -> Self {
|
||||
Self(HashSet::with_hasher(EntityHash))
|
||||
}
|
||||
|
||||
/// Creates an empty `EntityHashSet` with the specified capacity.
|
||||
///
|
||||
/// Equivalent to [`HashSet::with_capacity_and_hasher(n, EntityHash)`].
|
||||
///
|
||||
/// [`HashSet::with_capacity_and_hasher(n, EntityHash)`]: HashSet::with_capacity_and_hasher
|
||||
pub fn with_capacity(n: usize) -> Self {
|
||||
Self(HashSet::with_capacity_and_hasher(n, EntityHash))
|
||||
}
|
||||
|
||||
/// Returns the inner [`HashSet`].
|
||||
pub fn into_inner(self) -> HashSet<Entity, EntityHash> {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Clears the set, returning all elements in an iterator.
|
||||
///
|
||||
/// Equivalent to [`HashSet::drain`].
|
||||
pub fn drain(&mut self) -> Drain<'_> {
|
||||
Drain(self.0.drain(), PhantomData)
|
||||
}
|
||||
|
||||
/// An iterator visiting all elements in arbitrary order.
|
||||
/// The iterator element type is `&'a Entity`.
|
||||
///
|
||||
/// Equivalent to [`HashSet::iter`].
|
||||
pub fn iter(&self) -> Iter<'_> {
|
||||
Iter(self.0.iter(), PhantomData)
|
||||
}
|
||||
|
||||
/// Drains elements which are true under the given predicate,
|
||||
/// and returns an iterator over the removed items.
|
||||
///
|
||||
/// Equivalent to [`HashSet::extract_if`].
|
||||
pub fn extract_if<F: FnMut(&Entity) -> bool>(&mut self, f: F) -> ExtractIf<'_, F> {
|
||||
ExtractIf(self.0.extract_if(f), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for EntityHashSet {
|
||||
type Target = HashSet<Entity, EntityHash>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for EntityHashSet {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a EntityHashSet {
|
||||
type Item = &'a Entity;
|
||||
|
||||
type IntoIter = Iter<'a>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
Iter((&self.0).into_iter(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for EntityHashSet {
|
||||
type Item = Entity;
|
||||
|
||||
type IntoIter = IntoIter;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
IntoIter(self.0.into_iter(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl BitAnd for &EntityHashSet {
|
||||
type Output = EntityHashSet;
|
||||
|
||||
fn bitand(self, rhs: Self) -> Self::Output {
|
||||
EntityHashSet(self.0.bitand(&rhs.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl BitAndAssign<&EntityHashSet> for EntityHashSet {
|
||||
fn bitand_assign(&mut self, rhs: &Self) {
|
||||
self.0.bitand_assign(&rhs.0);
|
||||
}
|
||||
}
|
||||
|
||||
impl BitOr for &EntityHashSet {
|
||||
type Output = EntityHashSet;
|
||||
|
||||
fn bitor(self, rhs: Self) -> Self::Output {
|
||||
EntityHashSet(self.0.bitor(&rhs.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl BitOrAssign<&EntityHashSet> for EntityHashSet {
|
||||
fn bitor_assign(&mut self, rhs: &Self) {
|
||||
self.0.bitor_assign(&rhs.0);
|
||||
}
|
||||
}
|
||||
|
||||
impl BitXor for &EntityHashSet {
|
||||
type Output = EntityHashSet;
|
||||
|
||||
fn bitxor(self, rhs: Self) -> Self::Output {
|
||||
EntityHashSet(self.0.bitxor(&rhs.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl BitXorAssign<&EntityHashSet> for EntityHashSet {
|
||||
fn bitxor_assign(&mut self, rhs: &Self) {
|
||||
self.0.bitxor_assign(&rhs.0);
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for &EntityHashSet {
|
||||
type Output = EntityHashSet;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
EntityHashSet(self.0.sub(&rhs.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign<&EntityHashSet> for EntityHashSet {
|
||||
fn sub_assign(&mut self, rhs: &Self) {
|
||||
self.0.sub_assign(&rhs.0);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Extend<&'a Entity> for EntityHashSet {
|
||||
fn extend<T: IntoIterator<Item = &'a Entity>>(&mut self, iter: T) {
|
||||
self.0.extend(iter);
|
||||
}
|
||||
}
|
||||
|
||||
impl Extend<Entity> for EntityHashSet {
|
||||
fn extend<T: IntoIterator<Item = Entity>>(&mut self, iter: T) {
|
||||
self.0.extend(iter);
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> From<[Entity; N]> for EntityHashSet {
|
||||
fn from(value: [Entity; N]) -> Self {
|
||||
Self(HashSet::from_iter(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl FromIterator<Entity> for EntityHashSet {
|
||||
fn from_iter<I: IntoIterator<Item = Entity>>(iterable: I) -> Self {
|
||||
Self(HashSet::from_iter(iterable))
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the items of an [`EntityHashSet`].
|
||||
///
|
||||
/// This struct is created by the [`iter`] method on [`EntityHashSet`]. See its documentation for more.
|
||||
///
|
||||
/// [`iter`]: EntityHashSet::iter
|
||||
pub struct Iter<'a, S = EntityHash>(hash_set::Iter<'a, Entity>, PhantomData<S>);
|
||||
|
||||
impl<'a> Iter<'a> {
|
||||
/// Returns the inner [`Iter`](hash_set::Iter).
|
||||
pub fn into_inner(self) -> hash_set::Iter<'a, Entity> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Deref for Iter<'a> {
|
||||
type Target = hash_set::Iter<'a, Entity>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Iter<'_> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Iter<'a> {
|
||||
type Item = &'a Entity;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.0.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Iter<'_> {}
|
||||
|
||||
impl FusedIterator for Iter<'_> {}
|
||||
|
||||
impl Clone for Iter<'_> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Iter<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Iter").field(&self.0).field(&self.1).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Iter<'_> {
|
||||
fn default() -> Self {
|
||||
Self(Default::default(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: Iter stems from a correctly behaving `HashSet<Entity, EntityHash>`.
|
||||
unsafe impl EntitySetIterator for Iter<'_> {}
|
||||
|
||||
/// Owning iterator over the items of an [`EntityHashSet`].
|
||||
///
|
||||
/// This struct is created by the [`into_iter`] method on [`EntityHashSet`] (provided by the [`IntoIterator`] trait). See its documentation for more.
|
||||
///
|
||||
/// [`into_iter`]: EntityHashSet::into_iter
|
||||
pub struct IntoIter<S = EntityHash>(hash_set::IntoIter<Entity>, PhantomData<S>);
|
||||
|
||||
impl IntoIter {
|
||||
/// Returns the inner [`IntoIter`](hash_set::IntoIter).
|
||||
pub fn into_inner(self) -> hash_set::IntoIter<Entity> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for IntoIter {
|
||||
type Target = hash_set::IntoIter<Entity>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for IntoIter {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for IntoIter {
|
||||
type Item = Entity;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.0.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for IntoIter {}
|
||||
|
||||
impl FusedIterator for IntoIter {}
|
||||
|
||||
impl Debug for IntoIter {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("IntoIter")
|
||||
.field(&self.0)
|
||||
.field(&self.1)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for IntoIter {
|
||||
fn default() -> Self {
|
||||
Self(Default::default(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: IntoIter stems from a correctly behaving `HashSet<Entity, EntityHash>`.
|
||||
unsafe impl EntitySetIterator for IntoIter {}
|
||||
|
||||
/// A draining iterator over the items of an [`EntityHashSet`].
|
||||
///
|
||||
/// This struct is created by the [`drain`] method on [`EntityHashSet`]. See its documentation for more.
|
||||
///
|
||||
/// [`drain`]: EntityHashSet::drain
|
||||
pub struct Drain<'a, S = EntityHash>(hash_set::Drain<'a, Entity>, PhantomData<S>);
|
||||
|
||||
impl<'a> Drain<'a> {
|
||||
/// Returns the inner [`Drain`](hash_set::Drain).
|
||||
pub fn into_inner(self) -> hash_set::Drain<'a, Entity> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Deref for Drain<'a> {
|
||||
type Target = hash_set::Drain<'a, Entity>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Drain<'_> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Drain<'a> {
|
||||
type Item = Entity;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.0.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Drain<'_> {}
|
||||
|
||||
impl FusedIterator for Drain<'_> {}
|
||||
|
||||
impl Debug for Drain<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Drain")
|
||||
.field(&self.0)
|
||||
.field(&self.1)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: Drain stems from a correctly behaving `HashSet<Entity, EntityHash>`.
|
||||
unsafe impl EntitySetIterator for Drain<'_> {}
|
||||
|
||||
/// A draining iterator over entries of a [`EntityHashSet`] which don't satisfy the predicate `f`.
|
||||
///
|
||||
/// This struct is created by the [`extract_if`] method on [`EntityHashSet`]. See its documentation for more.
|
||||
///
|
||||
/// [`extract_if`]: EntityHashSet::extract_if
|
||||
pub struct ExtractIf<'a, F: FnMut(&Entity) -> bool, S = EntityHash>(
|
||||
hash_set::ExtractIf<'a, Entity, F>,
|
||||
PhantomData<S>,
|
||||
);
|
||||
|
||||
impl<'a, F: FnMut(&Entity) -> bool> ExtractIf<'a, F> {
|
||||
/// Returns the inner [`ExtractIf`](hash_set::ExtractIf).
|
||||
pub fn into_inner(self) -> hash_set::ExtractIf<'a, Entity, F> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, F: FnMut(&Entity) -> bool> Deref for ExtractIf<'a, F> {
|
||||
type Target = hash_set::ExtractIf<'a, Entity, F>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: FnMut(&Entity) -> bool> DerefMut for ExtractIf<'_, F> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, F: FnMut(&Entity) -> bool> Iterator for ExtractIf<'a, F> {
|
||||
type Item = Entity;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.0.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: FnMut(&Entity) -> bool> FusedIterator for ExtractIf<'_, F> {}
|
||||
|
||||
impl<F: FnMut(&Entity) -> bool> Debug for ExtractIf<'_, F> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("ExtractIf").finish()
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: ExtractIf stems from a correctly behaving `HashSet<Entity, EntityHash>`.
|
||||
unsafe impl<F: FnMut(&Entity) -> bool> EntitySetIterator for ExtractIf<'_, F> {}
|
||||
|
||||
// SAFETY: Difference stems from two correctly behaving `HashSet<Entity, EntityHash>`s.
|
||||
unsafe impl EntitySetIterator for hash_set::Difference<'_, Entity, EntityHash> {}
|
||||
|
||||
// SAFETY: Intersection stems from two correctly behaving `HashSet<Entity, EntityHash>`s.
|
||||
unsafe impl EntitySetIterator for hash_set::Intersection<'_, Entity, EntityHash> {}
|
||||
|
||||
// SAFETY: SymmetricDifference stems from two correctly behaving `HashSet<Entity, EntityHash>`s.
|
||||
unsafe impl EntitySetIterator for hash_set::SymmetricDifference<'_, Entity, EntityHash> {}
|
||||
|
||||
// SAFETY: Union stems from two correctly behaving `HashSet<Entity, EntityHash>`s.
|
||||
unsafe impl EntitySetIterator for hash_set::Union<'_, Entity, EntityHash> {}
|
@ -53,6 +53,12 @@ pub use visit_entities::*;
|
||||
mod hash;
|
||||
pub use hash::*;
|
||||
|
||||
mod hash_map;
|
||||
mod hash_set;
|
||||
|
||||
pub use hash_map::EntityHashMap;
|
||||
pub use hash_set::EntityHashSet;
|
||||
|
||||
use crate::{
|
||||
archetype::{ArchetypeId, ArchetypeRow},
|
||||
identifier::{
|
||||
|
@ -2,7 +2,7 @@ use alloc::vec::Vec;
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
use crate::{
|
||||
entity::{Entity, EntityHash, EntityHashMap, EntityHashSet},
|
||||
entity::{Entity, EntityHashMap, EntityHashSet},
|
||||
world::{
|
||||
error::EntityFetchError, unsafe_world_cell::UnsafeWorldCell, EntityMut, EntityRef,
|
||||
EntityWorldMut,
|
||||
@ -297,7 +297,7 @@ unsafe impl WorldEntityFetch for &'_ EntityHashSet {
|
||||
type DeferredMut<'w> = EntityHashMap<EntityMut<'w>>;
|
||||
|
||||
unsafe fn fetch_ref(self, cell: UnsafeWorldCell<'_>) -> Result<Self::Ref<'_>, Entity> {
|
||||
let mut refs = EntityHashMap::with_capacity_and_hasher(self.len(), EntityHash);
|
||||
let mut refs = EntityHashMap::with_capacity(self.len());
|
||||
for &id in self {
|
||||
let ecell = cell.get_entity(id).ok_or(id)?;
|
||||
// SAFETY: caller ensures that the world cell has read-only access to the entity.
|
||||
@ -310,7 +310,7 @@ unsafe impl WorldEntityFetch for &'_ EntityHashSet {
|
||||
self,
|
||||
cell: UnsafeWorldCell<'_>,
|
||||
) -> Result<Self::Mut<'_>, EntityFetchError> {
|
||||
let mut refs = EntityHashMap::with_capacity_and_hasher(self.len(), EntityHash);
|
||||
let mut refs = EntityHashMap::with_capacity(self.len());
|
||||
for &id in self {
|
||||
let ecell = cell
|
||||
.get_entity(id)
|
||||
|
@ -6,7 +6,7 @@ use bevy_color::ColorToComponents;
|
||||
use bevy_core_pipeline::core_3d::{Camera3d, CORE_3D_DEPTH_FORMAT};
|
||||
use bevy_derive::{Deref, DerefMut};
|
||||
use bevy_ecs::{
|
||||
entity::{EntityHash, EntityHashMap, EntityHashSet},
|
||||
entity::{EntityHashMap, EntityHashSet},
|
||||
prelude::*,
|
||||
system::lifetimeless::Read,
|
||||
};
|
||||
@ -1114,7 +1114,7 @@ pub fn prepare_lights(
|
||||
array_layer_count: None,
|
||||
});
|
||||
|
||||
let mut live_views = EntityHashSet::with_capacity_and_hasher(views_count, EntityHash);
|
||||
let mut live_views = EntityHashSet::with_capacity(views_count);
|
||||
|
||||
// set up light data for each view
|
||||
for (entity, extracted_view, clusters, maybe_layers, no_indirect_drawing) in sorted_cameras
|
||||
|
Loading…
Reference in New Issue
Block a user