From fe07081e9d078118d8e78e0d066432818de59e2a Mon Sep 17 00:00:00 2001 From: Victoron <59878206+Victoronz@users.noreply.github.com> Date: Wed, 19 Mar 2025 02:22:43 +0100 Subject: [PATCH 1/4] Allow entity wrappers in entity set and map types --- crates/bevy_ecs/src/entity/hash.rs | 40 +- crates/bevy_ecs/src/entity/hash_map.rs | 254 ++++-- crates/bevy_ecs/src/entity/hash_set.rs | 398 +++++--- crates/bevy_ecs/src/entity/index_map.rs | 855 +++++++++++++----- crates/bevy_ecs/src/entity/index_set.rs | 605 +++++++++---- .../relationship_source_collection.rs | 2 +- crates/bevy_pbr/src/prepass/mod.rs | 2 +- crates/bevy_render/src/sync_world.rs | 16 +- crates/bevy_sprite/src/mesh2d/material.rs | 5 +- 9 files changed, 1574 insertions(+), 603 deletions(-) diff --git a/crates/bevy_ecs/src/entity/hash.rs b/crates/bevy_ecs/src/entity/hash.rs index 35e01cebcdb6b..8ba65bccd0b94 100644 --- a/crates/bevy_ecs/src/entity/hash.rs +++ b/crates/bevy_ecs/src/entity/hash.rs @@ -1,8 +1,25 @@ -use core::hash::{BuildHasher, Hasher}; +use core::hash::{BuildHasher, Hash, Hasher}; #[cfg(feature = "bevy_reflect")] use bevy_reflect::{std_traits::ReflectDefault, Reflect}; +use crate::{ + bundle::Bundle, + world::{ + EntityMut, EntityMutExcept, EntityRef, EntityRefExcept, FilteredEntityMut, + FilteredEntityRef, + }, +}; + +use super::Entity; + +/// A combination of [`BuildHasher`] and [`Hash`] that can be trusted to behave correctly. +/// +/// # Safety +/// When used together, the `Hasher` produced by `Self` and +/// the `Hash` impl of `H` must produce deterministic hashes. +pub unsafe trait TrustedBuildHasher: BuildHasher {} + /// A [`BuildHasher`] that results in a [`EntityHasher`]. #[derive(Debug, Default, Clone)] #[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Default, Clone))] @@ -16,6 +33,27 @@ impl BuildHasher for EntityHash { } } +// SAFETY: EntityHasher hashes `Entity` deterministically. +unsafe impl TrustedBuildHasher for EntityHash {} + +// SAFETY: EntityHasher hashes `Entity` deterministically. +unsafe impl TrustedBuildHasher> for EntityHash {} + +// SAFETY: EntityHasher hashes `Entity` deterministically. +unsafe impl TrustedBuildHasher> for EntityHash {} + +// SAFETY: EntityHasher hashes `Entity` deterministically. +unsafe impl TrustedBuildHasher> for EntityHash {} + +// SAFETY: EntityHasher hashes `Entity` deterministically. +unsafe impl TrustedBuildHasher> for EntityHash {} + +// SAFETY: EntityHasher hashes `Entity` deterministically. +unsafe impl TrustedBuildHasher> for EntityHash {} + +// SAFETY: EntityHasher hashes `Entity` deterministically. +unsafe impl TrustedBuildHasher> for EntityHash {} + /// A very fast hash that is only designed to work on generational indices /// like [`Entity`](super::Entity). It will panic if attempting to hash a type containing /// non-u64 fields. diff --git a/crates/bevy_ecs/src/entity/hash_map.rs b/crates/bevy_ecs/src/entity/hash_map.rs index 39fbfb1d87946..396a83c69d057 100644 --- a/crates/bevy_ecs/src/entity/hash_map.rs +++ b/crates/bevy_ecs/src/entity/hash_map.rs @@ -1,9 +1,10 @@ -//! Contains the [`EntityHashMap`] type, a [`HashMap`] pre-configured to use [`EntityHash`] hashing. +//! Contains the [`EntityEquivalentHashMap`] type, a [`HashMap`] pre-configured to use [`EntityHash`] hashing. //! //! This module is a lightweight wrapper around Bevy's [`HashMap`] that is more performant for [`Entity`] keys. use core::{ fmt::{self, Debug, Formatter}, + hash::Hash, iter::FusedIterator, marker::PhantomData, ops::{Deref, DerefMut, Index}, @@ -13,16 +14,26 @@ use bevy_platform_support::collections::hash_map::{self, HashMap}; #[cfg(feature = "bevy_reflect")] use bevy_reflect::Reflect; -use super::{Entity, EntityHash, EntitySetIterator, TrustedEntityBorrow}; +use super::{Entity, EntityHash, EntitySetIterator, TrustedBuildHasher, TrustedEntityBorrow}; /// A [`HashMap`] pre-configured to use [`EntityHash`] hashing. #[cfg_attr(feature = "bevy_reflect", derive(Reflect))] #[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))] #[derive(Debug, Clone, PartialEq, Eq)] -pub struct EntityHashMap(pub(crate) HashMap); - -impl EntityHashMap { - /// Creates an empty `EntityHashMap`. +pub struct EntityEquivalentHashMap( + pub(crate) HashMap, +) +where + EntityHash: TrustedBuildHasher; + +/// A [`HashMap`] pre-configured to use [`EntityHash`] hashing with an [`Entity`]. +pub type EntityHashMap = EntityEquivalentHashMap; + +impl EntityEquivalentHashMap +where + EntityHash: TrustedBuildHasher, +{ + /// Creates an empty `EntityEquivalentHashMap`. /// /// Equivalent to [`HashMap::with_hasher(EntityHash)`]. /// @@ -31,7 +42,7 @@ impl EntityHashMap { Self(HashMap::with_hasher(EntityHash)) } - /// Creates an empty `EntityHashMap` with the specified capacity. + /// Creates an empty `EntityEquivalentHashMap` with the specified capacity. /// /// Equivalent to [`HashMap::with_capacity_and_hasher(n, EntityHash)`]. /// @@ -41,15 +52,15 @@ impl EntityHashMap { } /// Returns the inner [`HashMap`]. - pub fn into_inner(self) -> HashMap { + pub fn into_inner(self) -> HashMap { self.0 } /// An iterator visiting all keys in arbitrary order. - /// The iterator element type is `&'a Entity`. + /// The iterator element type is `&'a K`. /// /// Equivalent to [`HashMap::keys`]. - pub fn keys(&self) -> Keys<'_, V> { + pub fn keys(&self) -> Keys<'_, K, V> { Keys(self.0.keys(), PhantomData) } @@ -58,189 +69,282 @@ impl EntityHashMap { /// The iterator element type is [`Entity`]. /// /// Equivalent to [`HashMap::into_keys`]. - pub fn into_keys(self) -> IntoKeys { + pub fn into_keys(self) -> IntoKeys { IntoKeys(self.0.into_keys(), PhantomData) } } -impl Default for EntityHashMap { +impl Default for EntityEquivalentHashMap +where + EntityHash: TrustedBuildHasher, +{ fn default() -> Self { Self(Default::default()) } } -impl Deref for EntityHashMap { - type Target = HashMap; +impl Deref for EntityEquivalentHashMap +where + EntityHash: TrustedBuildHasher, +{ + type Target = HashMap; fn deref(&self) -> &Self::Target { &self.0 } } -impl DerefMut for EntityHashMap { +impl DerefMut for EntityEquivalentHashMap +where + EntityHash: TrustedBuildHasher, +{ fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } -impl<'a, V: Copy> Extend<&'a (Entity, V)> for EntityHashMap { - fn extend>(&mut self, iter: T) { +impl<'a, K: TrustedEntityBorrow + Hash + Copy, V: Copy> Extend<&'a (K, V)> + for EntityEquivalentHashMap +where + EntityHash: TrustedBuildHasher, +{ + fn extend>(&mut self, iter: I) { self.0.extend(iter); } } -impl<'a, V: Copy> Extend<(&'a Entity, &'a V)> for EntityHashMap { - fn extend>(&mut self, iter: T) { +impl<'a, K: TrustedEntityBorrow + Hash + Copy, V: Copy> Extend<(&'a K, &'a V)> + for EntityEquivalentHashMap +where + EntityHash: TrustedBuildHasher, +{ + fn extend>(&mut self, iter: I) { self.0.extend(iter); } } -impl Extend<(Entity, V)> for EntityHashMap { - fn extend>(&mut self, iter: T) { +impl Extend<(K, V)> for EntityEquivalentHashMap +where + EntityHash: TrustedBuildHasher, +{ + fn extend>(&mut self, iter: I) { self.0.extend(iter); } } -impl From<[(Entity, V); N]> for EntityHashMap { - fn from(value: [(Entity, V); N]) -> Self { +impl From<[(K, V); N]> + for EntityEquivalentHashMap +where + EntityHash: TrustedBuildHasher, +{ + fn from(value: [(K, V); N]) -> Self { Self(HashMap::from_iter(value)) } } -impl FromIterator<(Entity, V)> for EntityHashMap { - fn from_iter>(iterable: I) -> Self { +impl FromIterator<(K, V)> for EntityEquivalentHashMap +where + EntityHash: TrustedBuildHasher, +{ + fn from_iter>(iterable: I) -> Self { Self(HashMap::from_iter(iterable)) } } -impl Index<&Q> for EntityHashMap { +// `TrustedEntityBorrow` does not guarantee maintained equality on conversions from one implementer to another, +// so we restrict this impl to only keys of type `Entity`. +impl Index<&Q> for EntityHashMap { type Output = V; fn index(&self, key: &Q) -> &V { self.0.index(&key.entity()) } } -impl<'a, V> IntoIterator for &'a EntityHashMap { - type Item = (&'a Entity, &'a V); - type IntoIter = hash_map::Iter<'a, Entity, V>; +impl<'a, K: TrustedEntityBorrow + Hash, V> IntoIterator for &'a EntityEquivalentHashMap +where + EntityHash: TrustedBuildHasher, +{ + type Item = (&'a K, &'a V); + type IntoIter = hash_map::Iter<'a, K, V>; fn into_iter(self) -> Self::IntoIter { self.0.iter() } } -impl<'a, V> IntoIterator for &'a mut EntityHashMap { - type Item = (&'a Entity, &'a mut V); - type IntoIter = hash_map::IterMut<'a, Entity, V>; +impl<'a, K: TrustedEntityBorrow + Hash, V> IntoIterator for &'a mut EntityEquivalentHashMap +where + EntityHash: TrustedBuildHasher, +{ + type Item = (&'a K, &'a mut V); + type IntoIter = hash_map::IterMut<'a, K, V>; fn into_iter(self) -> Self::IntoIter { self.0.iter_mut() } } -impl IntoIterator for EntityHashMap { - type Item = (Entity, V); - type IntoIter = hash_map::IntoIter; +impl IntoIterator for EntityEquivalentHashMap +where + EntityHash: TrustedBuildHasher, +{ + type Item = (K, V); + type IntoIter = hash_map::IntoIter; 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`. +/// An iterator over the keys of a [`EntityEquivalentHashMap`] in arbitrary order. +/// The iterator element type is `&'a K`. /// -/// This struct is created by the [`keys`] method on [`EntityHashMap`]. See its documentation for more. +/// This struct is created by the [`keys`] method on [`EntityEquivalentHashMap`]. See its documentation for more. /// -/// [`keys`]: EntityHashMap::keys -pub struct Keys<'a, V, S = EntityHash>(hash_map::Keys<'a, Entity, V>, PhantomData); - -impl<'a, V> Keys<'a, V> { +/// [`keys`]: EntityEquivalentHashMap::keys +pub struct Keys<'a, K: TrustedEntityBorrow + Hash, V, S = EntityHash>( + hash_map::Keys<'a, K, V>, + PhantomData, +) +where + EntityHash: TrustedBuildHasher; + +impl<'a, K: TrustedEntityBorrow + Hash, V> Keys<'a, K, V> +where + EntityHash: TrustedBuildHasher, +{ /// Returns the inner [`Keys`](hash_map::Keys). - pub fn into_inner(self) -> hash_map::Keys<'a, Entity, V> { + pub fn into_inner(self) -> hash_map::Keys<'a, K, V> { self.0 } } -impl<'a, V> Deref for Keys<'a, V> { - type Target = hash_map::Keys<'a, Entity, V>; +impl<'a, K: TrustedEntityBorrow + Hash, V> Deref for Keys<'a, K, V> +where + EntityHash: TrustedBuildHasher, +{ + type Target = hash_map::Keys<'a, K, V>; fn deref(&self) -> &Self::Target { &self.0 } } -impl<'a, V> Iterator for Keys<'a, V> { - type Item = &'a Entity; +impl<'a, K: TrustedEntityBorrow + Hash, V> Iterator for Keys<'a, K, V> +where + EntityHash: TrustedBuildHasher, +{ + type Item = &'a K; fn next(&mut self) -> Option { self.0.next() } } -impl ExactSizeIterator for Keys<'_, V> {} +impl ExactSizeIterator for Keys<'_, K, V> where + EntityHash: TrustedBuildHasher +{ +} -impl FusedIterator for Keys<'_, V> {} +impl FusedIterator for Keys<'_, K, V> where + EntityHash: TrustedBuildHasher +{ +} -impl Clone for Keys<'_, V> { +impl Clone for Keys<'_, K, V> +where + EntityHash: TrustedBuildHasher, +{ fn clone(&self) -> Self { Self(self.0.clone(), PhantomData) } } -impl Debug for Keys<'_, V> { +impl Debug for Keys<'_, K, V> +where + EntityHash: TrustedBuildHasher, +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_tuple("Keys").field(&self.0).field(&self.1).finish() } } -impl Default for Keys<'_, V> { +impl Default for Keys<'_, K, V> +where + EntityHash: TrustedBuildHasher, +{ fn default() -> Self { Self(Default::default(), PhantomData) } } -// SAFETY: Keys stems from a correctly behaving `HashMap`. -unsafe impl EntitySetIterator for Keys<'_, V> {} +// SAFETY: Keys stems from a correctly behaving `HashMap`. +unsafe impl EntitySetIterator for Keys<'_, K, V> where + EntityHash: TrustedBuildHasher +{ +} -/// An owning iterator over the keys of a [`EntityHashMap`] in arbitrary order. +/// An owning iterator over the keys of a [`EntityEquivalentHashMap`] in arbitrary order. /// The iterator element type is [`Entity`]. /// -/// This struct is created by the [`into_keys`] method on [`EntityHashMap`]. +/// This struct is created by the [`into_keys`] method on [`EntityEquivalentHashMap`]. /// See its documentation for more. /// The map cannot be used after calling that method. /// -/// [`into_keys`]: EntityHashMap::into_keys -pub struct IntoKeys(hash_map::IntoKeys, PhantomData); - -impl IntoKeys { +/// [`into_keys`]: EntityEquivalentHashMap::into_keys +pub struct IntoKeys( + hash_map::IntoKeys, + PhantomData, +) +where + EntityHash: TrustedBuildHasher; + +impl IntoKeys +where + EntityHash: TrustedBuildHasher, +{ /// Returns the inner [`IntoKeys`](hash_map::IntoKeys). - pub fn into_inner(self) -> hash_map::IntoKeys { + pub fn into_inner(self) -> hash_map::IntoKeys { self.0 } } -impl Deref for IntoKeys { - type Target = hash_map::IntoKeys; +impl Deref for IntoKeys +where + EntityHash: TrustedBuildHasher, +{ + type Target = hash_map::IntoKeys; fn deref(&self) -> &Self::Target { &self.0 } } -impl Iterator for IntoKeys { - type Item = Entity; +impl Iterator for IntoKeys +where + EntityHash: TrustedBuildHasher, +{ + type Item = K; fn next(&mut self) -> Option { self.0.next() } } -impl ExactSizeIterator for IntoKeys {} +impl ExactSizeIterator for IntoKeys where + EntityHash: TrustedBuildHasher +{ +} -impl FusedIterator for IntoKeys {} +impl FusedIterator for IntoKeys where + EntityHash: TrustedBuildHasher +{ +} -impl Debug for IntoKeys { +impl Debug for IntoKeys +where + EntityHash: TrustedBuildHasher, +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_tuple("IntoKeys") .field(&self.0) @@ -249,14 +353,20 @@ impl Debug for IntoKeys { } } -impl Default for IntoKeys { +impl Default for IntoKeys +where + EntityHash: TrustedBuildHasher, +{ fn default() -> Self { Self(Default::default(), PhantomData) } } -// SAFETY: IntoKeys stems from a correctly behaving `HashMap`. -unsafe impl EntitySetIterator for IntoKeys {} +// SAFETY: IntoKeys stems from a correctly behaving `HashMap`. +unsafe impl EntitySetIterator for IntoKeys where + EntityHash: TrustedBuildHasher +{ +} #[cfg(test)] mod tests { @@ -266,7 +376,7 @@ mod tests { // Check that the HashMaps are Clone if the key/values are Clone assert_impl_all!(EntityHashMap::: Clone); - // EntityHashMap should implement Reflect + // EntityEquivalentHashMap should implement Reflect #[cfg(feature = "bevy_reflect")] assert_impl_all!(EntityHashMap::: Reflect); } diff --git a/crates/bevy_ecs/src/entity/hash_set.rs b/crates/bevy_ecs/src/entity/hash_set.rs index 91c1000c91c0b..726f61a77e779 100644 --- a/crates/bevy_ecs/src/entity/hash_set.rs +++ b/crates/bevy_ecs/src/entity/hash_set.rs @@ -1,9 +1,10 @@ -//! Contains the [`EntityHashSet`] type, a [`HashSet`] pre-configured to use [`EntityHash`] hashing. +//! Contains the [`EntityEquivalentHashSet`] type, a [`HashSet`] pre-configured to use [`EntityHash`] hashing. //! //! This module is a lightweight wrapper around Bevy's [`HashSet`] that is more performant for [`Entity`] keys. use core::{ fmt::{self, Debug, Formatter}, + hash::Hash, iter::FusedIterator, marker::PhantomData, ops::{ @@ -16,16 +17,29 @@ use bevy_platform_support::collections::hash_set::{self, HashSet}; #[cfg(feature = "bevy_reflect")] use bevy_reflect::Reflect; -use super::{Entity, EntityHash, EntitySet, EntitySetIterator, FromEntitySetIterator}; +use super::{ + Entity, EntityHash, EntitySet, EntitySetIterator, FromEntitySetIterator, TrustedBuildHasher, + TrustedEntityBorrow, +}; /// A [`HashSet`] pre-configured to use [`EntityHash`] hashing. #[cfg_attr(feature = "bevy_reflect", derive(Reflect))] #[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))] -#[derive(Debug, Clone, Default, PartialEq, Eq)] -pub struct EntityHashSet(pub(crate) HashSet); - -impl EntityHashSet { - /// Creates an empty `EntityHashSet`. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct EntityEquivalentHashSet( + pub(crate) HashSet, +) +where + EntityHash: TrustedBuildHasher; + +/// An [`HashSet`] pre-configured to use [`EntityHash`] hashing with an [`Entity`]. +pub type EntityHashSet = EntityEquivalentHashSet; + +impl EntityEquivalentHashSet +where + EntityHash: TrustedBuildHasher, +{ + /// Creates an empty `EntityEquivalentHashSet`. /// /// Equivalent to [`HashSet::with_hasher(EntityHash)`]. /// @@ -34,7 +48,7 @@ impl EntityHashSet { Self(HashSet::with_hasher(EntityHash)) } - /// Creates an empty `EntityHashSet` with the specified capacity. + /// Creates an empty `EntityEquivalentHashSet` with the specified capacity. /// /// Equivalent to [`HashSet::with_capacity_and_hasher(n, EntityHash)`]. /// @@ -54,14 +68,14 @@ impl EntityHashSet { } /// Returns the inner [`HashSet`]. - pub fn into_inner(self) -> HashSet { + pub fn into_inner(self) -> HashSet { self.0 } /// Clears the set, returning all elements in an iterator. /// /// Equivalent to [`HashSet::drain`]. - pub fn drain(&mut self) -> Drain<'_> { + pub fn drain(&mut self) -> Drain<'_, K> { Drain(self.0.drain(), PhantomData) } @@ -69,7 +83,7 @@ impl EntityHashSet { /// The iterator element type is `&'a Entity`. /// /// Equivalent to [`HashSet::iter`]. - pub fn iter(&self) -> Iter<'_> { + pub fn iter(&self) -> Iter<'_, K> { Iter(self.0.iter(), PhantomData) } @@ -77,129 +91,193 @@ impl EntityHashSet { /// and returns an iterator over the removed items. /// /// Equivalent to [`HashSet::extract_if`]. - pub fn extract_if bool>(&mut self, f: F) -> ExtractIf<'_, F> { + pub fn extract_if bool>(&mut self, f: F) -> ExtractIf<'_, K, F> { ExtractIf(self.0.extract_if(f), PhantomData) } } -impl Deref for EntityHashSet { - type Target = HashSet; +impl Deref for EntityEquivalentHashSet +where + EntityHash: TrustedBuildHasher, +{ + type Target = HashSet; fn deref(&self) -> &Self::Target { &self.0 } } -impl DerefMut for EntityHashSet { +impl DerefMut for EntityEquivalentHashSet +where + EntityHash: TrustedBuildHasher, +{ fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } -impl<'a> IntoIterator for &'a EntityHashSet { - type Item = &'a Entity; +impl<'a, K: TrustedEntityBorrow + Hash> IntoIterator for &'a EntityEquivalentHashSet +where + EntityHash: TrustedBuildHasher, +{ + type Item = &'a K; - type IntoIter = Iter<'a>; + type IntoIter = Iter<'a, K>; fn into_iter(self) -> Self::IntoIter { Iter((&self.0).into_iter(), PhantomData) } } -impl IntoIterator for EntityHashSet { - type Item = Entity; +impl IntoIterator for EntityEquivalentHashSet +where + EntityHash: TrustedBuildHasher, +{ + type Item = K; - type IntoIter = IntoIter; + type IntoIter = IntoIter; fn into_iter(self) -> Self::IntoIter { IntoIter(self.0.into_iter(), PhantomData) } } -impl BitAnd for &EntityHashSet { - type Output = EntityHashSet; +impl Default for EntityEquivalentHashSet +where + EntityHash: TrustedBuildHasher, +{ + fn default() -> Self { + Self(Default::default()) + } +} + +impl BitAnd for &EntityEquivalentHashSet +where + EntityHash: TrustedBuildHasher, +{ + type Output = EntityEquivalentHashSet; fn bitand(self, rhs: Self) -> Self::Output { - EntityHashSet(self.0.bitand(&rhs.0)) + EntityEquivalentHashSet(self.0.bitand(&rhs.0)) } } -impl BitAndAssign<&EntityHashSet> for EntityHashSet { +impl BitAndAssign<&EntityEquivalentHashSet> + for EntityEquivalentHashSet +where + EntityHash: TrustedBuildHasher, +{ fn bitand_assign(&mut self, rhs: &Self) { self.0.bitand_assign(&rhs.0); } } -impl BitOr for &EntityHashSet { - type Output = EntityHashSet; +impl BitOr for &EntityEquivalentHashSet +where + EntityHash: TrustedBuildHasher, +{ + type Output = EntityEquivalentHashSet; fn bitor(self, rhs: Self) -> Self::Output { - EntityHashSet(self.0.bitor(&rhs.0)) + EntityEquivalentHashSet(self.0.bitor(&rhs.0)) } } -impl BitOrAssign<&EntityHashSet> for EntityHashSet { +impl BitOrAssign<&EntityEquivalentHashSet> + for EntityEquivalentHashSet +where + EntityHash: TrustedBuildHasher, +{ fn bitor_assign(&mut self, rhs: &Self) { self.0.bitor_assign(&rhs.0); } } -impl BitXor for &EntityHashSet { - type Output = EntityHashSet; +impl BitXor for &EntityEquivalentHashSet +where + EntityHash: TrustedBuildHasher, +{ + type Output = EntityEquivalentHashSet; fn bitxor(self, rhs: Self) -> Self::Output { - EntityHashSet(self.0.bitxor(&rhs.0)) + EntityEquivalentHashSet(self.0.bitxor(&rhs.0)) } } -impl BitXorAssign<&EntityHashSet> for EntityHashSet { +impl BitXorAssign<&EntityEquivalentHashSet> + for EntityEquivalentHashSet +where + EntityHash: TrustedBuildHasher, +{ fn bitxor_assign(&mut self, rhs: &Self) { self.0.bitxor_assign(&rhs.0); } } -impl Sub for &EntityHashSet { - type Output = EntityHashSet; +impl Sub for &EntityEquivalentHashSet +where + EntityHash: TrustedBuildHasher, +{ + type Output = EntityEquivalentHashSet; fn sub(self, rhs: Self) -> Self::Output { - EntityHashSet(self.0.sub(&rhs.0)) + EntityEquivalentHashSet(self.0.sub(&rhs.0)) } } -impl SubAssign<&EntityHashSet> for EntityHashSet { +impl SubAssign<&EntityEquivalentHashSet> + for EntityEquivalentHashSet +where + EntityHash: TrustedBuildHasher, +{ fn sub_assign(&mut self, rhs: &Self) { self.0.sub_assign(&rhs.0); } } -impl<'a> Extend<&'a Entity> for EntityHashSet { - fn extend>(&mut self, iter: T) { +impl<'a, K: TrustedEntityBorrow + Hash + Copy> Extend<&'a K> for EntityEquivalentHashSet +where + EntityHash: TrustedBuildHasher, +{ + fn extend>(&mut self, iter: I) { self.0.extend(iter); } } -impl Extend for EntityHashSet { - fn extend>(&mut self, iter: T) { +impl Extend for EntityEquivalentHashSet +where + EntityHash: TrustedBuildHasher, +{ + fn extend>(&mut self, iter: I) { self.0.extend(iter); } } -impl From<[Entity; N]> for EntityHashSet { - fn from(value: [Entity; N]) -> Self { +impl From<[K; N]> for EntityEquivalentHashSet +where + EntityHash: TrustedBuildHasher, +{ + fn from(value: [K; N]) -> Self { Self(HashSet::from_iter(value)) } } -impl FromIterator for EntityHashSet { - fn from_iter>(iterable: I) -> Self { +impl FromIterator for EntityEquivalentHashSet +where + EntityHash: TrustedBuildHasher, +{ + fn from_iter>(iterable: I) -> Self { Self(HashSet::from_iter(iterable)) } } -impl FromEntitySetIterator for EntityHashSet { - fn from_entity_set_iter>(set_iter: I) -> Self { +impl FromEntitySetIterator for EntityEquivalentHashSet +where + EntityHash: TrustedBuildHasher, +{ + fn from_entity_set_iter>(set_iter: I) -> Self { let iter = set_iter.into_iter(); - let set = EntityHashSet::with_capacity(iter.size_hint().0); + let set = EntityEquivalentHashSet::with_capacity(iter.size_hint().0); iter.fold(set, |mut set, e| { // SAFETY: Every element in self is unique. unsafe { @@ -210,96 +288,120 @@ impl FromEntitySetIterator for EntityHashSet { } } -/// An iterator over the items of an [`EntityHashSet`]. +/// An iterator over the items of an [`EntityEquivalentHashSet`]. /// -/// This struct is created by the [`iter`] method on [`EntityHashSet`]. See its documentation for more. +/// This struct is created by the [`iter`] method on [`EntityEquivalentHashSet`]. See its documentation for more. /// -/// [`iter`]: EntityHashSet::iter -pub struct Iter<'a, S = EntityHash>(hash_set::Iter<'a, Entity>, PhantomData); +/// [`iter`]: EntityEquivalentHashSet::iter +pub struct Iter<'a, K: TrustedEntityBorrow + Hash, S = EntityHash>( + hash_set::Iter<'a, K>, + PhantomData, +); -impl<'a> Iter<'a> { +impl<'a, K: TrustedEntityBorrow + Hash> Iter<'a, K> { /// Returns the inner [`Iter`](hash_set::Iter). - pub fn into_inner(self) -> hash_set::Iter<'a, Entity> { + pub fn into_inner(self) -> hash_set::Iter<'a, K> { self.0 } } -impl<'a> Deref for Iter<'a> { - type Target = hash_set::Iter<'a, Entity>; +impl<'a, K: TrustedEntityBorrow + Hash> Deref for Iter<'a, K> { + type Target = hash_set::Iter<'a, K>; fn deref(&self) -> &Self::Target { &self.0 } } -impl<'a> Iterator for Iter<'a> { - type Item = &'a Entity; +impl<'a, K: TrustedEntityBorrow + Hash> Iterator for Iter<'a, K> { + type Item = &'a K; fn next(&mut self) -> Option { self.0.next() } } -impl ExactSizeIterator for Iter<'_> {} +impl ExactSizeIterator for Iter<'_, K> {} -impl FusedIterator for Iter<'_> {} +impl FusedIterator for Iter<'_, K> {} -impl Clone for Iter<'_> { +impl Clone for Iter<'_, K> { fn clone(&self) -> Self { Self(self.0.clone(), PhantomData) } } -impl Debug for Iter<'_> { +impl Debug for Iter<'_, K> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_tuple("Iter").field(&self.0).field(&self.1).finish() } } -impl Default for Iter<'_> { +impl Default for Iter<'_, K> { fn default() -> Self { Self(Default::default(), PhantomData) } } // SAFETY: Iter stems from a correctly behaving `HashSet`. -unsafe impl EntitySetIterator for Iter<'_> {} +unsafe impl EntitySetIterator for Iter<'_, K> {} -/// Owning iterator over the items of an [`EntityHashSet`]. +/// Owning iterator over the items of an [`EntityEquivalentHashSet`]. /// -/// This struct is created by the [`into_iter`] method on [`EntityHashSet`] (provided by the [`IntoIterator`] trait). See its documentation for more. +/// This struct is created by the [`into_iter`] method on [`EntityEquivalentHashSet`] (provided by the [`IntoIterator`] trait). See its documentation for more. /// -/// [`into_iter`]: EntityHashSet::into_iter -pub struct IntoIter(hash_set::IntoIter, PhantomData); +/// [`into_iter`]: EntityEquivalentHashSet::into_iter +pub struct IntoIter = EntityHash>( + hash_set::IntoIter, + PhantomData, +); -impl IntoIter { +impl IntoIter +where + EntityHash: TrustedBuildHasher, +{ /// Returns the inner [`IntoIter`](hash_set::IntoIter). - pub fn into_inner(self) -> hash_set::IntoIter { + pub fn into_inner(self) -> hash_set::IntoIter { self.0 } } -impl Deref for IntoIter { - type Target = hash_set::IntoIter; +impl Deref for IntoIter +where + EntityHash: TrustedBuildHasher, +{ + type Target = hash_set::IntoIter; fn deref(&self) -> &Self::Target { &self.0 } } -impl Iterator for IntoIter { - type Item = Entity; +impl Iterator for IntoIter +where + EntityHash: TrustedBuildHasher, +{ + type Item = K; fn next(&mut self) -> Option { self.0.next() } } -impl ExactSizeIterator for IntoIter {} +impl ExactSizeIterator for IntoIter where + EntityHash: TrustedBuildHasher +{ +} -impl FusedIterator for IntoIter {} +impl FusedIterator for IntoIter where + EntityHash: TrustedBuildHasher +{ +} -impl Debug for IntoIter { +impl Debug for IntoIter +where + EntityHash: TrustedBuildHasher, +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_tuple("IntoIter") .field(&self.0) @@ -308,50 +410,77 @@ impl Debug for IntoIter { } } -impl Default for IntoIter { +impl Default for IntoIter +where + EntityHash: TrustedBuildHasher, +{ fn default() -> Self { Self(Default::default(), PhantomData) } } // SAFETY: IntoIter stems from a correctly behaving `HashSet`. -unsafe impl EntitySetIterator for IntoIter {} +unsafe impl EntitySetIterator for IntoIter where + EntityHash: TrustedBuildHasher +{ +} -/// A draining iterator over the items of an [`EntityHashSet`]. +/// A draining iterator over the items of an [`EntityEquivalentHashSet`]. /// -/// This struct is created by the [`drain`] method on [`EntityHashSet`]. See its documentation for more. +/// This struct is created by the [`drain`] method on [`EntityEquivalentHashSet`]. See its documentation for more. /// -/// [`drain`]: EntityHashSet::drain -pub struct Drain<'a, S = EntityHash>(hash_set::Drain<'a, Entity>, PhantomData); +/// [`drain`]: EntityEquivalentHashSet::drain +pub struct Drain<'a, K: TrustedEntityBorrow + Hash, S: TrustedBuildHasher = EntityHash>( + hash_set::Drain<'a, K>, + PhantomData, +); -impl<'a> Drain<'a> { +impl<'a, K: TrustedEntityBorrow + Hash> Drain<'a, K> +where + EntityHash: TrustedBuildHasher, +{ /// Returns the inner [`Drain`](hash_set::Drain). - pub fn into_inner(self) -> hash_set::Drain<'a, Entity> { + pub fn into_inner(self) -> hash_set::Drain<'a, K> { self.0 } } -impl<'a> Deref for Drain<'a> { - type Target = hash_set::Drain<'a, Entity>; +impl<'a, K: TrustedEntityBorrow + Hash> Deref for Drain<'a, K> +where + EntityHash: TrustedBuildHasher, +{ + type Target = hash_set::Drain<'a, K>; fn deref(&self) -> &Self::Target { &self.0 } } -impl<'a> Iterator for Drain<'a> { - type Item = Entity; +impl<'a, K: TrustedEntityBorrow + Hash> Iterator for Drain<'a, K> +where + EntityHash: TrustedBuildHasher, +{ + type Item = K; fn next(&mut self) -> Option { self.0.next() } } -impl ExactSizeIterator for Drain<'_> {} +impl ExactSizeIterator for Drain<'_, K> where + EntityHash: TrustedBuildHasher +{ +} -impl FusedIterator for Drain<'_> {} +impl FusedIterator for Drain<'_, K> where + EntityHash: TrustedBuildHasher +{ +} -impl Debug for Drain<'_> { +impl Debug for Drain<'_, K> +where + EntityHash: TrustedBuildHasher, +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_tuple("Drain") .field(&self.0) @@ -361,60 +490,103 @@ impl Debug for Drain<'_> { } // SAFETY: Drain stems from a correctly behaving `HashSet`. -unsafe impl EntitySetIterator for Drain<'_> {} +unsafe impl EntitySetIterator for Drain<'_, K> where + EntityHash: TrustedBuildHasher +{ +} -/// A draining iterator over entries of a [`EntityHashSet`] which don't satisfy the predicate `f`. +/// A draining iterator over entries of a [`EntityEquivalentHashSet`] which don't satisfy the predicate `f`. /// -/// This struct is created by the [`extract_if`] method on [`EntityHashSet`]. See its documentation for more. +/// This struct is created by the [`extract_if`] method on [`EntityEquivalentHashSet`]. 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>, +/// [`extract_if`]: EntityEquivalentHashSet::extract_if +pub struct ExtractIf<'a, K: TrustedEntityBorrow + Hash, F: FnMut(&K) -> bool, S = EntityHash>( + hash_set::ExtractIf<'a, K, F>, PhantomData, -); - -impl<'a, F: FnMut(&Entity) -> bool> ExtractIf<'a, F> { +) +where + EntityHash: TrustedBuildHasher; + +impl<'a, K: TrustedEntityBorrow + Hash, F: FnMut(&K) -> bool> ExtractIf<'a, K, F> +where + EntityHash: TrustedBuildHasher, +{ /// Returns the inner [`ExtractIf`](hash_set::ExtractIf). - pub fn into_inner(self) -> hash_set::ExtractIf<'a, Entity, F> { + pub fn into_inner(self) -> hash_set::ExtractIf<'a, K, F> { self.0 } } -impl<'a, F: FnMut(&Entity) -> bool> Deref for ExtractIf<'a, F> { - type Target = hash_set::ExtractIf<'a, Entity, F>; +impl<'a, K: TrustedEntityBorrow + Hash, F: FnMut(&K) -> bool> Deref for ExtractIf<'a, K, F> +where + EntityHash: TrustedBuildHasher, +{ + type Target = hash_set::ExtractIf<'a, K, F>; fn deref(&self) -> &Self::Target { &self.0 } } -impl<'a, F: FnMut(&Entity) -> bool> Iterator for ExtractIf<'a, F> { - type Item = Entity; +impl<'a, K: TrustedEntityBorrow + Hash, F: FnMut(&K) -> bool> Iterator for ExtractIf<'a, K, F> +where + EntityHash: TrustedBuildHasher, +{ + type Item = K; fn next(&mut self) -> Option { self.0.next() } } -impl bool> FusedIterator for ExtractIf<'_, F> {} +impl bool> FusedIterator for ExtractIf<'_, K, F> where + EntityHash: TrustedBuildHasher +{ +} -impl bool> Debug for ExtractIf<'_, F> { +impl bool> Debug for ExtractIf<'_, K, F> +where + EntityHash: TrustedBuildHasher, +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_tuple("ExtractIf").finish() } } // SAFETY: ExtractIf stems from a correctly behaving `HashSet`. -unsafe impl bool> EntitySetIterator for ExtractIf<'_, F> {} +unsafe impl bool> EntitySetIterator + for ExtractIf<'_, K, F> +where + EntityHash: TrustedBuildHasher, +{ +} // SAFETY: Difference stems from two correctly behaving `HashSet`s. -unsafe impl EntitySetIterator for hash_set::Difference<'_, Entity, EntityHash> {} +unsafe impl EntitySetIterator + for hash_set::Difference<'_, K, EntityHash> +where + EntityHash: TrustedBuildHasher, +{ +} // SAFETY: Intersection stems from two correctly behaving `HashSet`s. -unsafe impl EntitySetIterator for hash_set::Intersection<'_, Entity, EntityHash> {} +unsafe impl EntitySetIterator + for hash_set::Intersection<'_, K, EntityHash> +where + EntityHash: TrustedBuildHasher, +{ +} // SAFETY: SymmetricDifference stems from two correctly behaving `HashSet`s. -unsafe impl EntitySetIterator for hash_set::SymmetricDifference<'_, Entity, EntityHash> {} +unsafe impl EntitySetIterator + for hash_set::SymmetricDifference<'_, K, EntityHash> +where + EntityHash: TrustedBuildHasher, +{ +} // SAFETY: Union stems from two correctly behaving `HashSet`s. -unsafe impl EntitySetIterator for hash_set::Union<'_, Entity, EntityHash> {} +unsafe impl EntitySetIterator for hash_set::Union<'_, K, EntityHash> where + EntityHash: TrustedBuildHasher +{ +} diff --git a/crates/bevy_ecs/src/entity/index_map.rs b/crates/bevy_ecs/src/entity/index_map.rs index de174ae3c83b2..f707d900638ba 100644 --- a/crates/bevy_ecs/src/entity/index_map.rs +++ b/crates/bevy_ecs/src/entity/index_map.rs @@ -1,4 +1,4 @@ -//! Contains the [`EntityIndexMap`] type, an [`IndexMap`] pre-configured to use [`EntityHash`] hashing. +//! Contains the [`EntityEquivalentIndexMap`] type, an [`IndexMap`] pre-configured to use [`EntityHash`] hashing. //! //! This module is a lightweight wrapper around `indexmap`'s [`IndexMap`] that is more performant for [`Entity`] keys. @@ -19,7 +19,7 @@ use core::{ use bevy_reflect::Reflect; use indexmap::map::{self, IndexMap, IntoValues, ValuesMut}; -use super::{Entity, EntityHash, EntitySetIterator, TrustedEntityBorrow}; +use super::{Entity, EntityHash, EntitySetIterator, TrustedBuildHasher, TrustedEntityBorrow}; use bevy_platform_support::prelude::Box; @@ -27,10 +27,20 @@ use bevy_platform_support::prelude::Box; #[cfg_attr(feature = "bevy_reflect", derive(Reflect))] #[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))] #[derive(Debug, Clone)] -pub struct EntityIndexMap(pub(crate) IndexMap); +pub struct EntityEquivalentIndexMap( + pub(crate) IndexMap, +) +where + EntityHash: TrustedBuildHasher; + +/// An [`IndexMap`] pre-configured to use [`EntityHash`] hashing with an [`Entity`]. +pub type EntityIndexMap = EntityEquivalentIndexMap; -impl EntityIndexMap { - /// Creates an empty `EntityIndexMap`. +impl EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ + /// Creates an empty `EntityEquivalentIndexMap`. /// /// Equivalent to [`IndexMap::with_hasher(EntityHash)`]. /// @@ -39,7 +49,7 @@ impl EntityIndexMap { Self(IndexMap::with_hasher(EntityHash)) } - /// Creates an empty `EntityIndexMap` with the specified capacity. + /// Creates an empty `EntityEquivalentIndexMap` with the specified capacity. /// /// Equivalent to [`IndexMap::with_capacity_and_hasher(n, EntityHash)`]. /// @@ -49,14 +59,14 @@ impl EntityIndexMap { } /// Returns the inner [`IndexMap`]. - pub fn into_inner(self) -> IndexMap { + pub fn into_inner(self) -> IndexMap { self.0 } /// Returns a slice of all the key-value pairs in the map. /// /// Equivalent to [`IndexMap::as_slice`]. - pub fn as_slice(&self) -> &Slice { + pub fn as_slice(&self) -> &Slice { // SAFETY: Slice is a transparent wrapper around indexmap::map::Slice. unsafe { Slice::from_slice_unchecked(self.0.as_slice()) } } @@ -64,7 +74,7 @@ impl EntityIndexMap { /// Returns a mutable slice of all the key-value pairs in the map. /// /// Equivalent to [`IndexMap::as_mut_slice`]. - pub fn as_mut_slice(&mut self) -> &mut Slice { + pub fn as_mut_slice(&mut self) -> &mut Slice { // SAFETY: Slice is a transparent wrapper around indexmap::map::Slice. unsafe { Slice::from_slice_unchecked_mut(self.0.as_mut_slice()) } } @@ -72,7 +82,7 @@ impl EntityIndexMap { /// Converts into a boxed slice of all the key-value pairs in the map. /// /// Equivalent to [`IndexMap::into_boxed_slice`]. - pub fn into_boxed_slice(self) -> Box> { + pub fn into_boxed_slice(self) -> Box> { // SAFETY: Slice is a transparent wrapper around indexmap::map::Slice. unsafe { Slice::from_boxed_slice_unchecked(self.0.into_boxed_slice()) } } @@ -80,7 +90,7 @@ impl EntityIndexMap { /// Returns a slice of key-value pairs in the given range of indices. /// /// Equivalent to [`IndexMap::get_range`]. - pub fn get_range>(&self, range: R) -> Option<&Slice> { + pub fn get_range>(&self, range: R) -> Option<&Slice> { self.0.get_range(range).map(|slice| // SAFETY: EntityIndexSetSlice is a transparent wrapper around indexmap::set::Slice. unsafe { Slice::from_slice_unchecked(slice) }) @@ -89,7 +99,7 @@ impl EntityIndexMap { /// Returns a mutable slice of key-value pairs in the given range of indices. /// /// Equivalent to [`IndexMap::get_range_mut`]. - pub fn get_range_mut>(&mut self, range: R) -> Option<&mut Slice> { + pub fn get_range_mut>(&mut self, range: R) -> Option<&mut Slice> { self.0.get_range_mut(range).map(|slice| // SAFETY: EntityIndexSetSlice is a transparent wrapper around indexmap::set::Slice. unsafe { Slice::from_slice_unchecked_mut(slice) }) @@ -98,14 +108,14 @@ impl EntityIndexMap { /// Return an iterator over the key-value pairs of the map, in their order. /// /// Equivalent to [`IndexMap::iter`]. - pub fn iter(&self) -> Iter<'_, V> { + pub fn iter(&self) -> Iter<'_, K, V> { Iter(self.0.iter(), PhantomData) } /// Return a mutable iterator over the key-value pairs of the map, in their order. /// /// Equivalent to [`IndexMap::iter_mut`]. - pub fn iter_mut(&mut self) -> IterMut<'_, V> { + pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { IterMut(self.0.iter_mut(), PhantomData) } @@ -113,69 +123,94 @@ impl EntityIndexMap { /// key-value pairs as a drain iterator. /// /// Equivalent to [`IndexMap::drain`]. - pub fn drain>(&mut self, range: R) -> Drain<'_, V> { + pub fn drain>(&mut self, range: R) -> Drain<'_, K, V> { Drain(self.0.drain(range), PhantomData) } /// Return an iterator over the keys of the map, in their order. /// /// Equivalent to [`IndexMap::keys`]. - pub fn keys(&self) -> Keys<'_, V> { + pub fn keys(&self) -> Keys<'_, K, V> { Keys(self.0.keys(), PhantomData) } /// Return an owning iterator over the keys of the map, in their order. /// /// Equivalent to [`IndexMap::into_keys`]. - pub fn into_keys(self) -> IntoKeys { + pub fn into_keys(self) -> IntoKeys { IntoKeys(self.0.into_keys(), PhantomData) } } -impl Default for EntityIndexMap { +impl Default for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ fn default() -> Self { Self(Default::default()) } } -impl Deref for EntityIndexMap { - type Target = IndexMap; +impl Deref for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ + type Target = IndexMap; fn deref(&self) -> &Self::Target { &self.0 } } -impl DerefMut for EntityIndexMap { +impl DerefMut for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } -impl<'a, V: Copy> Extend<(&'a Entity, &'a V)> for EntityIndexMap { - fn extend>(&mut self, iter: T) { +impl<'a, K: TrustedEntityBorrow + Hash + Copy, V: Copy> Extend<(&'a K, &'a V)> + for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ + fn extend>(&mut self, iter: I) { self.0.extend(iter); } } -impl Extend<(Entity, V)> for EntityIndexMap { - fn extend>(&mut self, iter: T) { +impl Extend<(K, V)> for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ + fn extend>(&mut self, iter: I) { self.0.extend(iter); } } -impl From<[(Entity, V); N]> for EntityIndexMap { - fn from(value: [(Entity, V); N]) -> Self { +impl From<[(K, V); N]> + for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ + fn from(value: [(K, V); N]) -> Self { Self(IndexMap::from_iter(value)) } } -impl FromIterator<(Entity, V)> for EntityIndexMap { - fn from_iter>(iterable: I) -> Self { +impl FromIterator<(K, V)> for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ + fn from_iter>(iterable: I) -> Self { Self(IndexMap::from_iter(iterable)) } } +// `TrustedEntityBorrow` does not guarantee maintained equality on conversions from one implementer to another, +// so we restrict this impl to only keys of type `Entity`. impl Index<&Q> for EntityIndexMap { type Output = V; fn index(&self, key: &Q) -> &V { @@ -183,186 +218,264 @@ impl Index<&Q> for EntityIndexMap { } } -impl Index<(Bound, Bound)> for EntityIndexMap { - type Output = Slice; +impl Index<(Bound, Bound)> + for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ + type Output = Slice; fn index(&self, key: (Bound, Bound)) -> &Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } } } -impl Index> for EntityIndexMap { - type Output = Slice; +impl Index> for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ + type Output = Slice; fn index(&self, key: Range) -> &Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } } } -impl Index> for EntityIndexMap { - type Output = Slice; +impl Index> for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ + type Output = Slice; fn index(&self, key: RangeFrom) -> &Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } } } -impl Index for EntityIndexMap { - type Output = Slice; +impl Index for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ + type Output = Slice; fn index(&self, key: RangeFull) -> &Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } } } -impl Index> for EntityIndexMap { - type Output = Slice; +impl Index> + for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ + type Output = Slice; fn index(&self, key: RangeInclusive) -> &Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } } } -impl Index> for EntityIndexMap { - type Output = Slice; +impl Index> for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ + type Output = Slice; fn index(&self, key: RangeTo) -> &Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } } } -impl Index> for EntityIndexMap { - type Output = Slice; +impl Index> + for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ + type Output = Slice; fn index(&self, key: RangeToInclusive) -> &Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } } } -impl Index for EntityIndexMap { +impl Index for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ type Output = V; fn index(&self, key: usize) -> &V { self.0.index(key) } } -impl IndexMut<&Q> for EntityIndexMap { +impl IndexMut<&Q> for EntityEquivalentIndexMap { fn index_mut(&mut self, key: &Q) -> &mut V { self.0.index_mut(&key.entity()) } } -impl IndexMut<(Bound, Bound)> for EntityIndexMap { +impl IndexMut<(Bound, Bound)> + for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ fn index_mut(&mut self, key: (Bound, Bound)) -> &mut Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked_mut(self.0.index_mut(key)) } } } -impl IndexMut> for EntityIndexMap { +impl IndexMut> for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ fn index_mut(&mut self, key: Range) -> &mut Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked_mut(self.0.index_mut(key)) } } } -impl IndexMut> for EntityIndexMap { +impl IndexMut> for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ fn index_mut(&mut self, key: RangeFrom) -> &mut Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked_mut(self.0.index_mut(key)) } } } -impl IndexMut for EntityIndexMap { +impl IndexMut for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ fn index_mut(&mut self, key: RangeFull) -> &mut Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked_mut(self.0.index_mut(key)) } } } -impl IndexMut> for EntityIndexMap { +impl IndexMut> + for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ fn index_mut(&mut self, key: RangeInclusive) -> &mut Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked_mut(self.0.index_mut(key)) } } } -impl IndexMut> for EntityIndexMap { +impl IndexMut> for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ fn index_mut(&mut self, key: RangeTo) -> &mut Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked_mut(self.0.index_mut(key)) } } } -impl IndexMut> for EntityIndexMap { +impl IndexMut> + for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ fn index_mut(&mut self, key: RangeToInclusive) -> &mut Self::Output { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked_mut(self.0.index_mut(key)) } } } -impl IndexMut for EntityIndexMap { +impl IndexMut for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ fn index_mut(&mut self, key: usize) -> &mut V { self.0.index_mut(key) } } -impl<'a, V> IntoIterator for &'a EntityIndexMap { - type Item = (&'a Entity, &'a V); - type IntoIter = Iter<'a, V>; +impl<'a, K: TrustedEntityBorrow + Hash, V> IntoIterator for &'a EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ + type Item = (&'a K, &'a V); + type IntoIter = Iter<'a, K, V>; fn into_iter(self) -> Self::IntoIter { Iter(self.0.iter(), PhantomData) } } -impl<'a, V> IntoIterator for &'a mut EntityIndexMap { - type Item = (&'a Entity, &'a mut V); - type IntoIter = IterMut<'a, V>; +impl<'a, K: TrustedEntityBorrow + Hash, V> IntoIterator for &'a mut EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ + type Item = (&'a K, &'a mut V); + type IntoIter = IterMut<'a, K, V>; fn into_iter(self) -> Self::IntoIter { IterMut(self.0.iter_mut(), PhantomData) } } -impl IntoIterator for EntityIndexMap { - type Item = (Entity, V); - type IntoIter = IntoIter; +impl IntoIterator for EntityEquivalentIndexMap +where + EntityHash: TrustedBuildHasher, +{ + type Item = (K, V); + type IntoIter = IntoIter; fn into_iter(self) -> Self::IntoIter { IntoIter(self.0.into_iter(), PhantomData) } } -impl PartialEq> for EntityIndexMap +impl PartialEq> + for EntityEquivalentIndexMap where + EntityHash: TrustedBuildHasher, V1: PartialEq, S2: BuildHasher, { - fn eq(&self, other: &IndexMap) -> bool { + fn eq(&self, other: &IndexMap) -> bool { self.0.eq(other) } } -impl PartialEq> for EntityIndexMap +impl PartialEq> + for EntityEquivalentIndexMap where + EntityHash: TrustedBuildHasher, V1: PartialEq, { - fn eq(&self, other: &EntityIndexMap) -> bool { + fn eq(&self, other: &EntityEquivalentIndexMap) -> bool { self.0.eq(other) } } -impl Eq for EntityIndexMap {} +impl Eq for EntityEquivalentIndexMap where + EntityHash: TrustedBuildHasher +{ +} -/// A dynamically-sized slice of key-value pairs in an [`EntityIndexMap`]. +/// A dynamically-sized slice of key-value pairs in an [`EntityEquivalentIndexMap`]. /// -/// Equivalent to an [`indexmap::map::Slice`] whose source [`IndexMap`] +/// Equivalent to an [`indexmap::map::Slice`] whose source [`IndexMap`] /// uses [`EntityHash`]. #[repr(transparent)] -pub struct Slice(PhantomData, map::Slice); +pub struct Slice( + PhantomData, + map::Slice, +) +where + EntityHash: TrustedBuildHasher; -impl Slice { +impl Slice +where + EntityHash: TrustedBuildHasher, +{ /// Returns an empty slice. /// /// Equivalent to [`map::Slice::new`]. @@ -386,7 +499,7 @@ impl Slice { /// `slice` must stem from an [`IndexMap`] using [`EntityHash`]. /// /// [`entity::index_map::Slice`]: `crate::entity::index_map::Slice` - pub const unsafe fn from_slice_unchecked(slice: &map::Slice) -> &Self { + pub const unsafe fn from_slice_unchecked(slice: &map::Slice) -> &Self { // SAFETY: Slice is a transparent wrapper around indexmap::map::Slice. unsafe { &*(ptr::from_ref(slice) as *const Self) } } @@ -398,13 +511,13 @@ impl Slice { /// `slice` must stem from an [`IndexMap`] using [`EntityHash`]. /// /// [`entity::index_map::Slice`]: `crate::entity::index_map::Slice` - pub const unsafe fn from_slice_unchecked_mut(slice: &mut map::Slice) -> &mut Self { + pub const unsafe fn from_slice_unchecked_mut(slice: &mut map::Slice) -> &mut Self { // SAFETY: Slice is a transparent wrapper around indexmap::map::Slice. unsafe { &mut *(ptr::from_mut(slice) as *mut Self) } } /// Casts `self` to the inner slice. - pub const fn as_inner(&self) -> &map::Slice { + pub const fn as_inner(&self) -> &map::Slice { &self.1 } @@ -415,7 +528,7 @@ impl Slice { /// `slice` must stem from an [`IndexMap`] using [`EntityHash`]. /// /// [`entity::index_map::Slice`]: `crate::entity::index_map::Slice` - pub unsafe fn from_boxed_slice_unchecked(slice: Box>) -> Box { + pub unsafe fn from_boxed_slice_unchecked(slice: Box>) -> Box { // SAFETY: Slice is a transparent wrapper around indexmap::map::Slice. unsafe { Box::from_raw(Box::into_raw(slice) as *mut Self) } } @@ -425,21 +538,21 @@ impl Slice { clippy::borrowed_box, reason = "We wish to access the Box API of the inner type, without consuming it." )] - pub fn as_boxed_inner(self: &Box) -> &Box> { + pub fn as_boxed_inner(self: &Box) -> &Box> { // SAFETY: Slice is a transparent wrapper around indexmap::map::Slice. - unsafe { &*(ptr::from_ref(self).cast::>>()) } + unsafe { &*(ptr::from_ref(self).cast::>>()) } } /// Casts `self` to the inner slice. - pub fn into_boxed_inner(self: Box) -> Box> { + pub fn into_boxed_inner(self: Box) -> Box> { // SAFETY: Slice is a transparent wrapper around indexmap::map::Slice. - unsafe { Box::from_raw(Box::into_raw(self) as *mut map::Slice) } + unsafe { Box::from_raw(Box::into_raw(self) as *mut map::Slice) } } /// Get a key-value pair by index, with mutable access to the value. /// /// Equivalent to [`map::Slice::get_index_mut`]. - pub fn get_index_mut(&mut self, index: usize) -> Option<(&Entity, &mut V)> { + pub fn get_index_mut(&mut self, index: usize) -> Option<(&K, &mut V)> { self.1.get_index_mut(index) } @@ -464,14 +577,14 @@ impl Slice { /// Get the first key-value pair, with mutable access to the value. /// /// Equivalent to [`map::Slice::first_mut`]. - pub fn first_mut(&mut self) -> Option<(&Entity, &mut V)> { + pub fn first_mut(&mut self) -> Option<(&K, &mut V)> { self.1.first_mut() } /// Get the last key-value pair, with mutable access to the value. /// /// Equivalent to [`map::Slice::last_mut`]. - pub fn last_mut(&mut self) -> Option<(&Entity, &mut V)> { + pub fn last_mut(&mut self) -> Option<(&K, &mut V)> { self.1.last_mut() } @@ -507,7 +620,7 @@ impl Slice { /// or `None` if it is empty. /// /// Equivalent to [`map::Slice::split_first`]. - pub fn split_first(&self) -> Option<((&Entity, &V), &Self)> { + pub fn split_first(&self) -> Option<((&K, &V), &Self)> { self.1.split_first().map(|(first, rest)| { ( first, @@ -521,7 +634,7 @@ impl Slice { /// with mutable access to the value, or `None` if it is empty. /// /// Equivalent to [`map::Slice::split_first_mut`]. - pub fn split_first_mut(&mut self) -> Option<((&Entity, &mut V), &mut Self)> { + pub fn split_first_mut(&mut self) -> Option<((&K, &mut V), &mut Self)> { self.1.split_first_mut().map(|(first, rest)| { ( first, @@ -535,7 +648,7 @@ impl Slice { /// or `None` if it is empty. /// /// Equivalent to [`map::Slice::split_last`]. - pub fn split_last(&self) -> Option<((&Entity, &V), &Self)> { + pub fn split_last(&self) -> Option<((&K, &V), &Self)> { self.1.split_last().map(|(last, rest)| { ( last, @@ -549,7 +662,7 @@ impl Slice { /// with mutable access to the value, or `None` if it is empty. /// /// Equivalent to [`map::Slice::split_last_mut`]. - pub fn split_last_mut(&mut self) -> Option<((&Entity, &mut V), &mut Self)> { + pub fn split_last_mut(&mut self) -> Option<((&K, &mut V), &mut Self)> { self.1.split_last_mut().map(|(last, rest)| { ( last, @@ -562,55 +675,61 @@ impl Slice { /// Return an iterator over the key-value pairs of the map slice. /// /// Equivalent to [`map::Slice::iter`]. - pub fn iter(&self) -> Iter<'_, V> { + pub fn iter(&self) -> Iter<'_, K, V> { Iter(self.1.iter(), PhantomData) } /// Return an iterator over the key-value pairs of the map slice. /// /// Equivalent to [`map::Slice::iter_mut`]. - pub fn iter_mut(&mut self) -> IterMut<'_, V> { + pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { IterMut(self.1.iter_mut(), PhantomData) } /// Return an iterator over the keys of the map slice. /// /// Equivalent to [`map::Slice::keys`]. - pub fn keys(&self) -> Keys<'_, V> { + pub fn keys(&self) -> Keys<'_, K, V> { Keys(self.1.keys(), PhantomData) } /// Return an owning iterator over the keys of the map slice. /// /// Equivalent to [`map::Slice::into_keys`]. - pub fn into_keys(self: Box) -> IntoKeys { + pub fn into_keys(self: Box) -> IntoKeys { IntoKeys(self.into_boxed_inner().into_keys(), PhantomData) } /// Return an iterator over mutable references to the the values of the map slice. /// /// Equivalent to [`map::Slice::values_mut`]. - pub fn values_mut(&mut self) -> ValuesMut<'_, Entity, V> { + pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> { self.1.values_mut() } /// Return an owning iterator over the values of the map slice. /// /// Equivalent to [`map::Slice::into_values`]. - pub fn into_values(self: Box) -> IntoValues { + pub fn into_values(self: Box) -> IntoValues { self.into_boxed_inner().into_values() } } -impl Deref for Slice { - type Target = map::Slice; +impl Deref for Slice +where + EntityHash: TrustedBuildHasher, +{ + type Target = map::Slice; fn deref(&self) -> &Self::Target { &self.1 } } -impl Debug for Slice { +impl Debug for Slice +where + EntityHash: TrustedBuildHasher, +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_tuple("Slice") .field(&self.0) @@ -619,95 +738,135 @@ impl Debug for Slice { } } -impl Clone for Box> { +impl Clone for Box> +where + EntityHash: TrustedBuildHasher, +{ fn clone(&self) -> Self { // SAFETY: This a clone of a valid slice. unsafe { Slice::from_boxed_slice_unchecked(self.as_boxed_inner().clone()) } } } -impl Default for &Slice { +impl Default for &Slice +where + EntityHash: TrustedBuildHasher, +{ fn default() -> Self { // SAFETY: The source slice is empty. - unsafe { Slice::from_slice_unchecked(<&map::Slice>::default()) } + unsafe { Slice::from_slice_unchecked(<&map::Slice>::default()) } } } -impl Default for &mut Slice { +impl Default for &mut Slice +where + EntityHash: TrustedBuildHasher, +{ fn default() -> Self { // SAFETY: The source slice is empty. - unsafe { Slice::from_slice_unchecked_mut(<&mut map::Slice>::default()) } + unsafe { Slice::from_slice_unchecked_mut(<&mut map::Slice>::default()) } } } -impl Default for Box> { +impl Default for Box> +where + EntityHash: TrustedBuildHasher, +{ fn default() -> Self { // SAFETY: The source slice is empty. - unsafe { Slice::from_boxed_slice_unchecked(>>::default()) } + unsafe { Slice::from_boxed_slice_unchecked(>>::default()) } } } -impl From<&Slice> for Box> { - fn from(value: &Slice) -> Self { +impl From<&Slice> for Box> +where + EntityHash: TrustedBuildHasher, +{ + fn from(value: &Slice) -> Self { // SAFETY: This slice is a copy of a valid slice. unsafe { Slice::from_boxed_slice_unchecked(value.1.into()) } } } -impl Hash for Slice { +impl Hash for Slice +where + EntityHash: TrustedBuildHasher, +{ fn hash(&self, state: &mut H) { self.1.hash(state); } } -impl<'a, V> IntoIterator for &'a Slice { - type Item = (&'a Entity, &'a V); - type IntoIter = Iter<'a, V>; +impl<'a, K: TrustedEntityBorrow + Hash, V> IntoIterator for &'a Slice +where + EntityHash: TrustedBuildHasher, +{ + type Item = (&'a K, &'a V); + type IntoIter = Iter<'a, K, V>; fn into_iter(self) -> Self::IntoIter { Iter(self.1.iter(), PhantomData) } } -impl<'a, V> IntoIterator for &'a mut Slice { - type Item = (&'a Entity, &'a mut V); - type IntoIter = IterMut<'a, V>; +impl<'a, K: TrustedEntityBorrow + Hash, V> IntoIterator for &'a mut Slice +where + EntityHash: TrustedBuildHasher, +{ + type Item = (&'a K, &'a mut V); + type IntoIter = IterMut<'a, K, V>; fn into_iter(self) -> Self::IntoIter { IterMut(self.1.iter_mut(), PhantomData) } } -impl IntoIterator for Box> { - type Item = (Entity, V); - type IntoIter = IntoIter; +impl IntoIterator for Box> +where + EntityHash: TrustedBuildHasher, +{ + type Item = (K, V); + type IntoIter = IntoIter; fn into_iter(self) -> Self::IntoIter { IntoIter(self.into_boxed_inner().into_iter(), PhantomData) } } -impl PartialOrd for Slice { +impl PartialOrd for Slice +where + EntityHash: TrustedBuildHasher, +{ fn partial_cmp(&self, other: &Self) -> Option { self.1.partial_cmp(&other.1) } } -impl Ord for Slice { +impl Ord for Slice +where + EntityHash: TrustedBuildHasher, +{ fn cmp(&self, other: &Self) -> Ordering { self.1.cmp(other) } } -impl PartialEq for Slice { +impl PartialEq for Slice +where + EntityHash: TrustedBuildHasher, +{ fn eq(&self, other: &Self) -> bool { self.1 == other.1 } } -impl Eq for Slice {} +impl Eq for Slice where EntityHash: TrustedBuildHasher +{} -impl Index<(Bound, Bound)> for Slice { +impl Index<(Bound, Bound)> for Slice +where + EntityHash: TrustedBuildHasher, +{ type Output = Self; fn index(&self, key: (Bound, Bound)) -> &Self { // SAFETY: This a subslice of a valid slice. @@ -715,7 +874,10 @@ impl Index<(Bound, Bound)> for Slice { } } -impl Index> for Slice { +impl Index> for Slice +where + EntityHash: TrustedBuildHasher, +{ type Output = Self; fn index(&self, key: Range) -> &Self { // SAFETY: This a subslice of a valid slice. @@ -723,7 +885,10 @@ impl Index> for Slice { } } -impl Index> for Slice { +impl Index> for Slice +where + EntityHash: TrustedBuildHasher, +{ type Output = Self; fn index(&self, key: RangeFrom) -> &Self { // SAFETY: This a subslice of a valid slice. @@ -731,7 +896,10 @@ impl Index> for Slice { } } -impl Index for Slice { +impl Index for Slice +where + EntityHash: TrustedBuildHasher, +{ type Output = Self; fn index(&self, key: RangeFull) -> &Self { // SAFETY: This a subslice of a valid slice. @@ -739,7 +907,10 @@ impl Index for Slice { } } -impl Index> for Slice { +impl Index> for Slice +where + EntityHash: TrustedBuildHasher, +{ type Output = Self; fn index(&self, key: RangeInclusive) -> &Self { // SAFETY: This a subslice of a valid slice. @@ -747,7 +918,10 @@ impl Index> for Slice { } } -impl Index> for Slice { +impl Index> for Slice +where + EntityHash: TrustedBuildHasher, +{ type Output = Self; fn index(&self, key: RangeTo) -> &Self { // SAFETY: This a subslice of a valid slice. @@ -755,7 +929,10 @@ impl Index> for Slice { } } -impl Index> for Slice { +impl Index> for Slice +where + EntityHash: TrustedBuildHasher, +{ type Output = Self; fn index(&self, key: RangeToInclusive) -> &Self { // SAFETY: This a subslice of a valid slice. @@ -763,149 +940,216 @@ impl Index> for Slice { } } -impl Index for Slice { +impl Index for Slice +where + EntityHash: TrustedBuildHasher, +{ type Output = V; fn index(&self, key: usize) -> &V { self.1.index(key) } } -impl IndexMut<(Bound, Bound)> for Slice { +impl IndexMut<(Bound, Bound)> for Slice +where + EntityHash: TrustedBuildHasher, +{ fn index_mut(&mut self, key: (Bound, Bound)) -> &mut Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked_mut(self.1.index_mut(key)) } } } -impl IndexMut> for Slice { +impl IndexMut> for Slice +where + EntityHash: TrustedBuildHasher, +{ fn index_mut(&mut self, key: Range) -> &mut Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked_mut(self.1.index_mut(key)) } } } -impl IndexMut> for Slice { +impl IndexMut> for Slice +where + EntityHash: TrustedBuildHasher, +{ fn index_mut(&mut self, key: RangeFrom) -> &mut Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked_mut(self.1.index_mut(key)) } } } -impl IndexMut for Slice { +impl IndexMut for Slice +where + EntityHash: TrustedBuildHasher, +{ fn index_mut(&mut self, key: RangeFull) -> &mut Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked_mut(self.1.index_mut(key)) } } } -impl IndexMut> for Slice { +impl IndexMut> for Slice +where + EntityHash: TrustedBuildHasher, +{ fn index_mut(&mut self, key: RangeInclusive) -> &mut Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked_mut(self.1.index_mut(key)) } } } -impl IndexMut> for Slice { +impl IndexMut> for Slice +where + EntityHash: TrustedBuildHasher, +{ fn index_mut(&mut self, key: RangeTo) -> &mut Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked_mut(self.1.index_mut(key)) } } } -impl IndexMut> for Slice { +impl IndexMut> for Slice +where + EntityHash: TrustedBuildHasher, +{ fn index_mut(&mut self, key: RangeToInclusive) -> &mut Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked_mut(self.1.index_mut(key)) } } } -impl IndexMut for Slice { +impl IndexMut for Slice +where + EntityHash: TrustedBuildHasher, +{ fn index_mut(&mut self, key: usize) -> &mut V { self.1.index_mut(key) } } -/// An iterator over the entries of an [`EntityIndexMap`]. +/// An iterator over the entries of an [`EntityEquivalentIndexMap`]. /// -/// This `struct` is created by the [`EntityIndexMap::iter`] method. +/// This `struct` is created by the [`EntityEquivalentIndexMap::iter`] method. /// See its documentation for more. -pub struct Iter<'a, V, S = EntityHash>(map::Iter<'a, Entity, V>, PhantomData); +pub struct Iter<'a, K: TrustedEntityBorrow + Hash, V, S = EntityHash>( + map::Iter<'a, K, V>, + PhantomData, +) +where + EntityHash: TrustedBuildHasher; -impl<'a, V> Iter<'a, V> { +impl<'a, K: TrustedEntityBorrow + Hash, V> Iter<'a, K, V> +where + EntityHash: TrustedBuildHasher, +{ /// Returns the inner [`Iter`](map::Iter). - pub fn into_inner(self) -> map::Iter<'a, Entity, V> { + pub fn into_inner(self) -> map::Iter<'a, K, V> { self.0 } /// Returns a slice of the remaining entries in the iterator. /// /// Equivalent to [`map::Iter::as_slice`]. - pub fn as_slice(&self) -> &Slice { + pub fn as_slice(&self) -> &Slice { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.as_slice()) } } } -impl<'a, V> Deref for Iter<'a, V> { - type Target = map::Iter<'a, Entity, V>; +impl<'a, K: TrustedEntityBorrow + Hash, V> Deref for Iter<'a, K, V> +where + EntityHash: TrustedBuildHasher, +{ + type Target = map::Iter<'a, K, V>; fn deref(&self) -> &Self::Target { &self.0 } } -impl<'a, V> Iterator for Iter<'a, V> { - type Item = (&'a Entity, &'a V); +impl<'a, K: TrustedEntityBorrow + Hash, V> Iterator for Iter<'a, K, V> +where + EntityHash: TrustedBuildHasher, +{ + type Item = (&'a K, &'a V); fn next(&mut self) -> Option { self.0.next() } } -impl DoubleEndedIterator for Iter<'_, V> { +impl DoubleEndedIterator for Iter<'_, K, V> +where + EntityHash: TrustedBuildHasher, +{ fn next_back(&mut self) -> Option { self.0.next_back() } } -impl ExactSizeIterator for Iter<'_, V> {} +impl ExactSizeIterator for Iter<'_, K, V> where + EntityHash: TrustedBuildHasher +{ +} -impl FusedIterator for Iter<'_, V> {} +impl FusedIterator for Iter<'_, K, V> where + EntityHash: TrustedBuildHasher +{ +} -impl Clone for Iter<'_, V> { +impl Clone for Iter<'_, K, V> +where + EntityHash: TrustedBuildHasher, +{ fn clone(&self) -> Self { Self(self.0.clone(), PhantomData) } } -impl Debug for Iter<'_, V> { +impl Debug for Iter<'_, K, V> +where + EntityHash: TrustedBuildHasher, +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_tuple("Iter").field(&self.0).field(&self.1).finish() } } -impl Default for Iter<'_, V> { +impl Default for Iter<'_, K, V> +where + EntityHash: TrustedBuildHasher, +{ fn default() -> Self { Self(Default::default(), PhantomData) } } -/// A mutable iterator over the entries of an [`EntityIndexMap`]. +/// A mutable iterator over the entries of an [`EntityEquivalentIndexMap`]. /// -/// This `struct` is created by the [`EntityIndexMap::iter_mut`] method. +/// This `struct` is created by the [`EntityEquivalentIndexMap::iter_mut`] method. /// See its documentation for more. -pub struct IterMut<'a, V, S = EntityHash>(map::IterMut<'a, Entity, V>, PhantomData); +pub struct IterMut<'a, K: TrustedEntityBorrow + Hash, V, S = EntityHash>( + map::IterMut<'a, K, V>, + PhantomData, +) +where + EntityHash: TrustedBuildHasher; -impl<'a, V> IterMut<'a, V> { +impl<'a, K: TrustedEntityBorrow + Hash, V> IterMut<'a, K, V> +where + EntityHash: TrustedBuildHasher, +{ /// Returns the inner [`IterMut`](map::IterMut). - pub fn into_inner(self) -> map::IterMut<'a, Entity, V> { + pub fn into_inner(self) -> map::IterMut<'a, K, V> { self.0 } /// Returns a slice of the remaining entries in the iterator. /// /// Equivalent to [`map::IterMut::as_slice`]. - pub fn as_slice(&self) -> &Slice { + pub fn as_slice(&self) -> &Slice { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.as_slice()) } } @@ -913,39 +1157,57 @@ impl<'a, V> IterMut<'a, V> { /// Returns a mutable slice of the remaining entries in the iterator. /// /// Equivalent to [`map::IterMut::into_slice`]. - pub fn into_slice(self) -> &'a mut Slice { + pub fn into_slice(self) -> &'a mut Slice { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked_mut(self.0.into_slice()) } } } -impl<'a, V> Deref for IterMut<'a, V> { - type Target = map::IterMut<'a, Entity, V>; +impl<'a, K: TrustedEntityBorrow + Hash, V> Deref for IterMut<'a, K, V> +where + EntityHash: TrustedBuildHasher, +{ + type Target = map::IterMut<'a, K, V>; fn deref(&self) -> &Self::Target { &self.0 } } -impl<'a, V> Iterator for IterMut<'a, V> { - type Item = (&'a Entity, &'a mut V); +impl<'a, K: TrustedEntityBorrow + Hash, V> Iterator for IterMut<'a, K, V> +where + EntityHash: TrustedBuildHasher, +{ + type Item = (&'a K, &'a mut V); fn next(&mut self) -> Option { self.0.next() } } -impl DoubleEndedIterator for IterMut<'_, V> { +impl DoubleEndedIterator for IterMut<'_, K, V> +where + EntityHash: TrustedBuildHasher, +{ fn next_back(&mut self) -> Option { self.0.next_back() } } -impl ExactSizeIterator for IterMut<'_, V> {} +impl ExactSizeIterator for IterMut<'_, K, V> where + EntityHash: TrustedBuildHasher +{ +} -impl FusedIterator for IterMut<'_, V> {} +impl FusedIterator for IterMut<'_, K, V> where + EntityHash: TrustedBuildHasher +{ +} -impl Debug for IterMut<'_, V> { +impl Debug for IterMut<'_, K, V> +where + EntityHash: TrustedBuildHasher, +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_tuple("IterMut") .field(&self.0) @@ -954,7 +1216,10 @@ impl Debug for IterMut<'_, V> { } } -impl Default for IterMut<'_, V> { +impl Default for IterMut<'_, K, V> +where + EntityHash: TrustedBuildHasher, +{ fn default() -> Self { Self(Default::default(), PhantomData) } @@ -964,18 +1229,26 @@ impl Default for IterMut<'_, V> { /// /// This `struct` is created by the [`IndexMap::into_iter`] method /// (provided by the [`IntoIterator`] trait). See its documentation for more. -pub struct IntoIter(map::IntoIter, PhantomData); +pub struct IntoIter( + map::IntoIter, + PhantomData, +) +where + EntityHash: TrustedBuildHasher; -impl IntoIter { +impl IntoIter +where + EntityHash: TrustedBuildHasher, +{ /// Returns the inner [`IntoIter`](map::IntoIter). - pub fn into_inner(self) -> map::IntoIter { + pub fn into_inner(self) -> map::IntoIter { self.0 } /// Returns a slice of the remaining entries in the iterator. /// /// Equivalent to [`map::IntoIter::as_slice`]. - pub fn as_slice(&self) -> &Slice { + pub fn as_slice(&self) -> &Slice { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.as_slice()) } } @@ -983,45 +1256,66 @@ impl IntoIter { /// Returns a mutable slice of the remaining entries in the iterator. /// /// Equivalent to [`map::IntoIter::as_mut_slice`]. - pub fn as_mut_slice(&mut self) -> &mut Slice { + pub fn as_mut_slice(&mut self) -> &mut Slice { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked_mut(self.0.as_mut_slice()) } } } -impl Deref for IntoIter { - type Target = map::IntoIter; +impl Deref for IntoIter +where + EntityHash: TrustedBuildHasher, +{ + type Target = map::IntoIter; fn deref(&self) -> &Self::Target { &self.0 } } -impl Iterator for IntoIter { - type Item = (Entity, V); +impl Iterator for IntoIter +where + EntityHash: TrustedBuildHasher, +{ + type Item = (K, V); fn next(&mut self) -> Option { self.0.next() } } -impl DoubleEndedIterator for IntoIter { +impl DoubleEndedIterator for IntoIter +where + EntityHash: TrustedBuildHasher, +{ fn next_back(&mut self) -> Option { self.0.next_back() } } -impl ExactSizeIterator for IntoIter {} +impl ExactSizeIterator for IntoIter where + EntityHash: TrustedBuildHasher +{ +} -impl FusedIterator for IntoIter {} +impl FusedIterator for IntoIter where + EntityHash: TrustedBuildHasher +{ +} -impl Clone for IntoIter { +impl Clone for IntoIter +where + EntityHash: TrustedBuildHasher, +{ fn clone(&self) -> Self { Self(self.0.clone(), PhantomData) } } -impl Debug for IntoIter { +impl Debug for IntoIter +where + EntityHash: TrustedBuildHasher, +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_tuple("IntoIter") .field(&self.0) @@ -1030,60 +1324,89 @@ impl Debug for IntoIter { } } -impl Default for IntoIter { +impl Default for IntoIter +where + EntityHash: TrustedBuildHasher, +{ fn default() -> Self { Self(Default::default(), PhantomData) } } -/// A draining iterator over the entries of an [`EntityIndexMap`]. +/// A draining iterator over the entries of an [`EntityEquivalentIndexMap`]. /// -/// This `struct` is created by the [`EntityIndexMap::drain`] method. +/// This `struct` is created by the [`EntityEquivalentIndexMap::drain`] method. /// See its documentation for more. -pub struct Drain<'a, V, S = EntityHash>(map::Drain<'a, Entity, V>, PhantomData); +pub struct Drain<'a, K: TrustedEntityBorrow + Hash, V, S = EntityHash>( + map::Drain<'a, K, V>, + PhantomData, +) +where + EntityHash: TrustedBuildHasher; -impl<'a, V> Drain<'a, V> { +impl<'a, K: TrustedEntityBorrow + Hash, V> Drain<'a, K, V> +where + EntityHash: TrustedBuildHasher, +{ /// Returns the inner [`Drain`](map::Drain). - pub fn into_inner(self) -> map::Drain<'a, Entity, V> { + pub fn into_inner(self) -> map::Drain<'a, K, V> { self.0 } /// Returns a slice of the remaining entries in the iterator. /// /// Equivalent to [`map::Drain::as_slice`]. - pub fn as_slice(&self) -> &Slice { + pub fn as_slice(&self) -> &Slice { // SAFETY: The source IndexMap uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.as_slice()) } } } -impl<'a, V> Deref for Drain<'a, V> { - type Target = map::Drain<'a, Entity, V>; +impl<'a, K: TrustedEntityBorrow + Hash, V> Deref for Drain<'a, K, V> +where + EntityHash: TrustedBuildHasher, +{ + type Target = map::Drain<'a, K, V>; fn deref(&self) -> &Self::Target { &self.0 } } -impl Iterator for Drain<'_, V> { - type Item = (Entity, V); +impl Iterator for Drain<'_, K, V> +where + EntityHash: TrustedBuildHasher, +{ + type Item = (K, V); fn next(&mut self) -> Option { self.0.next() } } -impl DoubleEndedIterator for Drain<'_, V> { +impl DoubleEndedIterator for Drain<'_, K, V> +where + EntityHash: TrustedBuildHasher, +{ fn next_back(&mut self) -> Option { self.0.next_back() } } -impl ExactSizeIterator for Drain<'_, V> {} +impl ExactSizeIterator for Drain<'_, K, V> where + EntityHash: TrustedBuildHasher +{ +} -impl FusedIterator for Drain<'_, V> {} +impl FusedIterator for Drain<'_, K, V> where + EntityHash: TrustedBuildHasher +{ +} -impl Debug for Drain<'_, V> { +impl Debug for Drain<'_, K, V> +where + EntityHash: TrustedBuildHasher, +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_tuple("Drain") .field(&self.0) @@ -1092,114 +1415,178 @@ impl Debug for Drain<'_, V> { } } -/// An iterator over the keys of an [`EntityIndexMap`]. +/// An iterator over the keys of an [`EntityEquivalentIndexMap`]. /// -/// This `struct` is created by the [`EntityIndexMap::keys`] method. +/// This `struct` is created by the [`EntityEquivalentIndexMap::keys`] method. /// See its documentation for more. -pub struct Keys<'a, V, S = EntityHash>(map::Keys<'a, Entity, V>, PhantomData); +pub struct Keys<'a, K: TrustedEntityBorrow + Hash, V, S = EntityHash>( + map::Keys<'a, K, V>, + PhantomData, +) +where + EntityHash: TrustedBuildHasher; -impl<'a, V> Keys<'a, V> { +impl<'a, K: TrustedEntityBorrow + Hash, V> Keys<'a, K, V> +where + EntityHash: TrustedBuildHasher, +{ /// Returns the inner [`Keys`](map::Keys). - pub fn into_inner(self) -> map::Keys<'a, Entity, V> { + pub fn into_inner(self) -> map::Keys<'a, K, V> { self.0 } } -impl<'a, V, S> Deref for Keys<'a, V, S> { - type Target = map::Keys<'a, Entity, V>; +impl<'a, K: TrustedEntityBorrow + Hash, V, S> Deref for Keys<'a, K, V, S> +where + EntityHash: TrustedBuildHasher, +{ + type Target = map::Keys<'a, K, V>; fn deref(&self) -> &Self::Target { &self.0 } } -impl<'a, V> Iterator for Keys<'a, V> { - type Item = &'a Entity; +impl<'a, K: TrustedEntityBorrow + Hash, V> Iterator for Keys<'a, K, V> +where + EntityHash: TrustedBuildHasher, +{ + type Item = &'a K; fn next(&mut self) -> Option { self.0.next() } } -impl DoubleEndedIterator for Keys<'_, V> { +impl DoubleEndedIterator for Keys<'_, K, V> +where + EntityHash: TrustedBuildHasher, +{ fn next_back(&mut self) -> Option { self.0.next_back() } } -impl ExactSizeIterator for Keys<'_, V> {} +impl ExactSizeIterator for Keys<'_, K, V> where + EntityHash: TrustedBuildHasher +{ +} -impl FusedIterator for Keys<'_, V> {} +impl FusedIterator for Keys<'_, K, V> where + EntityHash: TrustedBuildHasher +{ +} -impl Index for Keys<'_, V> { - type Output = Entity; +impl Index for Keys<'_, K, V> +where + EntityHash: TrustedBuildHasher, +{ + type Output = K; - fn index(&self, index: usize) -> &Entity { + fn index(&self, index: usize) -> &K { self.0.index(index) } } -impl Clone for Keys<'_, V> { +impl Clone for Keys<'_, K, V> +where + EntityHash: TrustedBuildHasher, +{ fn clone(&self) -> Self { Self(self.0.clone(), PhantomData) } } -impl Debug for Keys<'_, V> { +impl Debug for Keys<'_, K, V> +where + EntityHash: TrustedBuildHasher, +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_tuple("Keys").field(&self.0).field(&self.1).finish() } } -impl Default for Keys<'_, V> { +impl Default for Keys<'_, K, V> +where + EntityHash: TrustedBuildHasher, +{ fn default() -> Self { Self(Default::default(), PhantomData) } } -// SAFETY: Keys stems from a correctly behaving `IndexMap`. -unsafe impl EntitySetIterator for Keys<'_, V> {} +// SAFETY: Keys stems from a correctly behaving `IndexMap`. +unsafe impl EntitySetIterator for Keys<'_, K, V> where + EntityHash: TrustedBuildHasher +{ +} -/// An owning iterator over the keys of an [`EntityIndexMap`]. +/// An owning iterator over the keys of an [`EntityEquivalentIndexMap`]. /// -/// This `struct` is created by the [`EntityIndexMap::into_keys`] method. +/// This `struct` is created by the [`EntityEquivalentIndexMap::into_keys`] method. /// See its documentation for more. -pub struct IntoKeys(map::IntoKeys, PhantomData); +pub struct IntoKeys( + map::IntoKeys, + PhantomData, +) +where + EntityHash: TrustedBuildHasher; -impl IntoKeys { +impl IntoKeys +where + EntityHash: TrustedBuildHasher, +{ /// Returns the inner [`IntoKeys`](map::IntoKeys). - pub fn into_inner(self) -> map::IntoKeys { + pub fn into_inner(self) -> map::IntoKeys { self.0 } } -impl Deref for IntoKeys { - type Target = map::IntoKeys; +impl Deref for IntoKeys +where + EntityHash: TrustedBuildHasher, +{ + type Target = map::IntoKeys; fn deref(&self) -> &Self::Target { &self.0 } } -impl Iterator for IntoKeys { - type Item = Entity; +impl Iterator for IntoKeys +where + EntityHash: TrustedBuildHasher, +{ + type Item = K; fn next(&mut self) -> Option { self.0.next() } } -impl DoubleEndedIterator for IntoKeys { +impl DoubleEndedIterator for IntoKeys +where + EntityHash: TrustedBuildHasher, +{ fn next_back(&mut self) -> Option { self.0.next_back() } } -impl ExactSizeIterator for IntoKeys {} +impl ExactSizeIterator for IntoKeys where + EntityHash: TrustedBuildHasher +{ +} -impl FusedIterator for IntoKeys {} +impl FusedIterator for IntoKeys where + EntityHash: TrustedBuildHasher +{ +} -impl Debug for IntoKeys { +impl Debug for IntoKeys +where + EntityHash: TrustedBuildHasher, +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_tuple("IntoKeys") .field(&self.0) @@ -1208,11 +1595,17 @@ impl Debug for IntoKeys { } } -impl Default for IntoKeys { +impl Default for IntoKeys +where + EntityHash: TrustedBuildHasher, +{ fn default() -> Self { Self(Default::default(), PhantomData) } } -// SAFETY: IntoKeys stems from a correctly behaving `IndexMap`. -unsafe impl EntitySetIterator for IntoKeys {} +// SAFETY: IntoKeys stems from a correctly behaving `IndexMap`. +unsafe impl EntitySetIterator for IntoKeys where + EntityHash: TrustedBuildHasher +{ +} diff --git a/crates/bevy_ecs/src/entity/index_set.rs b/crates/bevy_ecs/src/entity/index_set.rs index 1af46994f6a2c..9d3ccee2efc17 100644 --- a/crates/bevy_ecs/src/entity/index_set.rs +++ b/crates/bevy_ecs/src/entity/index_set.rs @@ -1,4 +1,4 @@ -//! Contains the [`EntityIndexSet`] type, a [`IndexSet`] pre-configured to use [`EntityHash`] hashing. +//! Contains the [`EntityEquivalentIndexSet`] type, a [`IndexSet`] pre-configured to use [`EntityHash`] hashing. //! //! This module is a lightweight wrapper around `indexmap`'ss [`IndexSet`] that is more performant for [`Entity`] keys. @@ -18,17 +18,27 @@ use core::{ use indexmap::set::{self, IndexSet}; -use super::{Entity, EntityHash, EntitySetIterator}; +use super::{Entity, EntityHash, EntitySetIterator, TrustedBuildHasher, TrustedEntityBorrow}; use bevy_platform_support::prelude::Box; /// An [`IndexSet`] pre-configured to use [`EntityHash`] hashing. #[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))] #[derive(Debug, Clone, Default)] -pub struct EntityIndexSet(pub(crate) IndexSet); +pub struct EntityEquivalentIndexSet( + pub(crate) IndexSet, +) +where + EntityHash: TrustedBuildHasher; + +/// An [`IndexSet`] pre-configured to use [`EntityHash`] hashing with an [`Entity`]. +pub type EntityIndexSet = EntityEquivalentIndexSet; -impl EntityIndexSet { - /// Creates an empty `EntityIndexSet`. +impl EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + /// Creates an empty `EntityEquivalentIndexSet`. /// /// Equivalent to [`IndexSet::with_hasher(EntityHash)`]. /// @@ -37,7 +47,7 @@ impl EntityIndexSet { Self(IndexSet::with_hasher(EntityHash)) } - /// Creates an empty `EntityIndexSet` with the specified capacity. + /// Creates an empty `EntityEquivalentIndexSet` with the specified capacity. /// /// Equivalent to [`IndexSet::with_capacity_and_hasher(n, EntityHash)`]. /// @@ -47,14 +57,14 @@ impl EntityIndexSet { } /// Returns the inner [`IndexSet`]. - pub fn into_inner(self) -> IndexSet { + pub fn into_inner(self) -> IndexSet { self.0 } /// Returns a slice of all the values in the set. /// /// Equivalent to [`IndexSet::as_slice`]. - pub fn as_slice(&self) -> &Slice { + pub fn as_slice(&self) -> &Slice { // SAFETY: Slice is a transparent wrapper around indexmap::set::Slice. unsafe { Slice::from_slice_unchecked(self.0.as_slice()) } } @@ -63,14 +73,14 @@ impl EntityIndexSet { /// as a drain iterator. /// /// Equivalent to [`IndexSet::drain`]. - pub fn drain>(&mut self, range: R) -> Drain<'_> { + pub fn drain>(&mut self, range: R) -> Drain<'_, K> { Drain(self.0.drain(range), PhantomData) } /// Returns a slice of values in the given range of indices. /// /// Equivalent to [`IndexSet::get_range`]. - pub fn get_range>(&self, range: R) -> Option<&Slice> { + pub fn get_range>(&self, range: R) -> Option<&Slice> { self.0.get_range(range).map(|slice| // SAFETY: The source IndexSet uses EntityHash. unsafe { Slice::from_slice_unchecked(slice) }) @@ -79,203 +89,276 @@ impl EntityIndexSet { /// Return an iterator over the values of the set, in their order. /// /// Equivalent to [`IndexSet::iter`]. - pub fn iter(&self) -> Iter<'_> { + pub fn iter(&self) -> Iter<'_, K> { Iter(self.0.iter(), PhantomData) } /// Converts into a boxed slice of all the values in the set. /// /// Equivalent to [`IndexSet::into_boxed_slice`]. - pub fn into_boxed_slice(self) -> Box { + pub fn into_boxed_slice(self) -> Box> { // SAFETY: Slice is a transparent wrapper around indexmap::set::Slice. unsafe { Slice::from_boxed_slice_unchecked(self.0.into_boxed_slice()) } } } -impl Deref for EntityIndexSet { - type Target = IndexSet; +impl Deref for EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + type Target = IndexSet; fn deref(&self) -> &Self::Target { &self.0 } } -impl DerefMut for EntityIndexSet { +impl DerefMut for EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } -impl<'a> IntoIterator for &'a EntityIndexSet { - type Item = &'a Entity; +impl<'a, K: TrustedEntityBorrow + Hash> IntoIterator for &'a EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + type Item = &'a K; - type IntoIter = Iter<'a>; + type IntoIter = Iter<'a, K>; fn into_iter(self) -> Self::IntoIter { Iter((&self.0).into_iter(), PhantomData) } } -impl IntoIterator for EntityIndexSet { - type Item = Entity; +impl IntoIterator for EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + type Item = K; - type IntoIter = IntoIter; + type IntoIter = IntoIter; fn into_iter(self) -> Self::IntoIter { IntoIter(self.0.into_iter(), PhantomData) } } -impl BitAnd for &EntityIndexSet { - type Output = EntityIndexSet; +impl BitAnd for &EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + type Output = EntityEquivalentIndexSet; fn bitand(self, rhs: Self) -> Self::Output { - EntityIndexSet(self.0.bitand(&rhs.0)) + EntityEquivalentIndexSet(self.0.bitand(&rhs.0)) } } -impl BitOr for &EntityIndexSet { - type Output = EntityIndexSet; +impl BitOr for &EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + type Output = EntityEquivalentIndexSet; fn bitor(self, rhs: Self) -> Self::Output { - EntityIndexSet(self.0.bitor(&rhs.0)) + EntityEquivalentIndexSet(self.0.bitor(&rhs.0)) } } -impl BitXor for &EntityIndexSet { - type Output = EntityIndexSet; +impl BitXor for &EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + type Output = EntityEquivalentIndexSet; fn bitxor(self, rhs: Self) -> Self::Output { - EntityIndexSet(self.0.bitxor(&rhs.0)) + EntityEquivalentIndexSet(self.0.bitxor(&rhs.0)) } } -impl Sub for &EntityIndexSet { - type Output = EntityIndexSet; +impl Sub for &EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + type Output = EntityEquivalentIndexSet; fn sub(self, rhs: Self) -> Self::Output { - EntityIndexSet(self.0.sub(&rhs.0)) + EntityEquivalentIndexSet(self.0.sub(&rhs.0)) } } -impl<'a> Extend<&'a Entity> for EntityIndexSet { - fn extend>(&mut self, iter: T) { +impl<'a, K: TrustedEntityBorrow + Hash + Copy> Extend<&'a K> for EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + fn extend>(&mut self, iter: I) { self.0.extend(iter); } } -impl Extend for EntityIndexSet { - fn extend>(&mut self, iter: T) { +impl Extend for EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + fn extend>(&mut self, iter: I) { self.0.extend(iter); } } -impl From<[Entity; N]> for EntityIndexSet { - fn from(value: [Entity; N]) -> Self { +impl From<[K; N]> for EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + fn from(value: [K; N]) -> Self { Self(IndexSet::from_iter(value)) } } -impl FromIterator for EntityIndexSet { - fn from_iter>(iterable: I) -> Self { +impl FromIterator for EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + fn from_iter>(iterable: I) -> Self { Self(IndexSet::from_iter(iterable)) } } -impl PartialEq> for EntityIndexSet +impl PartialEq> for EntityEquivalentIndexSet where + EntityHash: TrustedBuildHasher, S2: BuildHasher, { - fn eq(&self, other: &IndexSet) -> bool { + fn eq(&self, other: &IndexSet) -> bool { self.0.eq(other) } } -impl PartialEq for EntityIndexSet { - fn eq(&self, other: &EntityIndexSet) -> bool { +impl PartialEq for EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + fn eq(&self, other: &EntityEquivalentIndexSet) -> bool { self.0.eq(other) } } -impl Eq for EntityIndexSet {} +impl Eq for EntityEquivalentIndexSet where + EntityHash: TrustedBuildHasher +{ +} -impl Index<(Bound, Bound)> for EntityIndexSet { - type Output = Slice; +impl Index<(Bound, Bound)> + for EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + type Output = Slice; fn index(&self, key: (Bound, Bound)) -> &Self::Output { // SAFETY: The source IndexSet uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } } } -impl Index> for EntityIndexSet { - type Output = Slice; +impl Index> for EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + type Output = Slice; fn index(&self, key: Range) -> &Self::Output { // SAFETY: The source IndexSet uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } } } -impl Index> for EntityIndexSet { - type Output = Slice; +impl Index> for EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + type Output = Slice; fn index(&self, key: RangeFrom) -> &Self::Output { // SAFETY: The source IndexSet uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } } } -impl Index for EntityIndexSet { - type Output = Slice; +impl Index for EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + type Output = Slice; fn index(&self, key: RangeFull) -> &Self::Output { // SAFETY: The source IndexSet uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } } } -impl Index> for EntityIndexSet { - type Output = Slice; +impl Index> for EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + type Output = Slice; fn index(&self, key: RangeInclusive) -> &Self::Output { // SAFETY: The source IndexSet uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } } } -impl Index> for EntityIndexSet { - type Output = Slice; +impl Index> for EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + type Output = Slice; fn index(&self, key: RangeTo) -> &Self::Output { // SAFETY: The source IndexSet uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } } } -impl Index> for EntityIndexSet { - type Output = Slice; +impl Index> for EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + type Output = Slice; fn index(&self, key: RangeToInclusive) -> &Self::Output { // SAFETY: The source IndexSet uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.index(key)) } } } -impl Index for EntityIndexSet { - type Output = Entity; - fn index(&self, key: usize) -> &Entity { +impl Index for EntityEquivalentIndexSet +where + EntityHash: TrustedBuildHasher, +{ + type Output = K; + fn index(&self, key: usize) -> &K { self.0.index(key) } } -/// A dynamically-sized slice of values in an [`EntityIndexSet`]. +/// A dynamically-sized slice of values in an [`EntityEquivalentIndexSet`]. /// /// Equivalent to an [`indexmap::set::Slice`] whose source [`IndexSet`] /// uses [`EntityHash`]. #[repr(transparent)] -pub struct Slice(PhantomData, set::Slice); +pub struct Slice(PhantomData, set::Slice) +where + EntityHash: TrustedBuildHasher; -impl Slice { +impl Slice +where + EntityHash: TrustedBuildHasher, +{ /// Returns an empty slice. /// /// Equivalent to [`set::Slice::new`]. pub const fn new<'a>() -> &'a Self { // SAFETY: The source slice is empty. - unsafe { Self::from_slice_unchecked(set::Slice::new()) } + unsafe { Self::from_slice_unchecked(set::Slice::::new()) } } /// Constructs a [`entity::index_set::Slice`] from a [`indexmap::set::Slice`] unsafely. @@ -285,7 +368,7 @@ impl Slice { /// `slice` must stem from an [`IndexSet`] using [`EntityHash`]. /// /// [`entity::index_set::Slice`]: `crate::entity::index_set::Slice` - pub const unsafe fn from_slice_unchecked(slice: &set::Slice) -> &Self { + pub const unsafe fn from_slice_unchecked(slice: &set::Slice) -> &Self { // SAFETY: Slice is a transparent wrapper around indexmap::set::Slice. unsafe { &*(ptr::from_ref(slice) as *const Self) } } @@ -297,13 +380,13 @@ impl Slice { /// `slice` must stem from an [`IndexSet`] using [`EntityHash`]. /// /// [`entity::index_set::Slice`]: `crate::entity::index_set::Slice` - pub const unsafe fn from_slice_unchecked_mut(slice: &mut set::Slice) -> &mut Self { + pub const unsafe fn from_slice_unchecked_mut(slice: &mut set::Slice) -> &mut Self { // SAFETY: Slice is a transparent wrapper around indexmap::set::Slice. unsafe { &mut *(ptr::from_mut(slice) as *mut Self) } } /// Casts `self` to the inner slice. - pub const fn as_inner(&self) -> &set::Slice { + pub const fn as_inner(&self) -> &set::Slice { &self.1 } @@ -314,7 +397,7 @@ impl Slice { /// `slice` must stem from an [`IndexSet`] using [`EntityHash`]. /// /// [`entity::index_set::Slice`]: `crate::entity::index_set::Slice` - pub unsafe fn from_boxed_slice_unchecked(slice: Box>) -> Box { + pub unsafe fn from_boxed_slice_unchecked(slice: Box>) -> Box { // SAFETY: Slice is a transparent wrapper around indexmap::set::Slice. unsafe { Box::from_raw(Box::into_raw(slice) as *mut Self) } } @@ -324,15 +407,15 @@ impl Slice { clippy::borrowed_box, reason = "We wish to access the Box API of the inner type, without consuming it." )] - pub fn as_boxed_inner(self: &Box) -> &Box> { + pub fn as_boxed_inner(self: &Box) -> &Box> { // SAFETY: Slice is a transparent wrapper around indexmap::set::Slice. - unsafe { &*(ptr::from_ref(self).cast::>>()) } + unsafe { &*(ptr::from_ref(self).cast::>>()) } } /// Casts `self` to the inner slice. - pub fn into_boxed_inner(self: Box) -> Box> { + pub fn into_boxed_inner(self: Box) -> Box> { // SAFETY: Slice is a transparent wrapper around indexmap::set::Slice. - unsafe { Box::from_raw(Box::into_raw(self) as *mut set::Slice) } + unsafe { Box::from_raw(Box::into_raw(self) as *mut set::Slice) } } /// Returns a slice of values in the given range of indices. @@ -362,7 +445,7 @@ impl Slice { /// or `None` if it is empty. /// /// Equivalent to [`set::Slice::split_first`]. - pub fn split_first(&self) -> Option<(&Entity, &Self)> { + pub fn split_first(&self) -> Option<(&K, &Self)> { self.1.split_first().map(|(first, rest)| { ( first, @@ -376,7 +459,7 @@ impl Slice { /// or `None` if it is empty. /// /// Equivalent to [`set::Slice::split_last`]. - pub fn split_last(&self) -> Option<(&Entity, &Self)> { + pub fn split_last(&self) -> Option<(&K, &Self)> { self.1.split_last().map(|(last, rest)| { ( last, @@ -389,59 +472,80 @@ impl Slice { /// Return an iterator over the values of the set slice. /// /// Equivalent to [`set::Slice::iter`]. - pub fn iter(&self) -> Iter<'_> { + pub fn iter(&self) -> Iter<'_, K> { Iter(self.1.iter(), PhantomData) } } -impl Deref for Slice { - type Target = set::Slice; +impl Deref for Slice +where + EntityHash: TrustedBuildHasher, +{ + type Target = set::Slice; fn deref(&self) -> &Self::Target { &self.1 } } -impl<'a> IntoIterator for &'a Slice { - type IntoIter = Iter<'a>; - type Item = &'a Entity; +impl<'a, K: TrustedEntityBorrow + Hash> IntoIterator for &'a Slice +where + EntityHash: TrustedBuildHasher, +{ + type IntoIter = Iter<'a, K>; + type Item = &'a K; fn into_iter(self) -> Self::IntoIter { self.iter() } } -impl IntoIterator for Box { - type IntoIter = IntoIter; - type Item = Entity; +impl IntoIterator for Box> +where + EntityHash: TrustedBuildHasher, +{ + type IntoIter = IntoIter; + type Item = K; fn into_iter(self) -> Self::IntoIter { IntoIter(self.into_boxed_inner().into_iter(), PhantomData) } } -impl Clone for Box { +impl Clone for Box> +where + EntityHash: TrustedBuildHasher, +{ fn clone(&self) -> Self { // SAFETY: This is a clone of a valid slice. unsafe { Slice::from_boxed_slice_unchecked(self.as_boxed_inner().clone()) } } } -impl Default for &Slice { +impl Default for &Slice +where + EntityHash: TrustedBuildHasher, +{ fn default() -> Self { // SAFETY: The source slice is empty. - unsafe { Slice::from_slice_unchecked(<&set::Slice>::default()) } + unsafe { Slice::from_slice_unchecked(<&set::Slice>::default()) } } } -impl Default for Box { +impl Default for Box> +where + EntityHash: TrustedBuildHasher, +{ fn default() -> Self { // SAFETY: The source slice is empty. - unsafe { Slice::from_boxed_slice_unchecked(>>::default()) } + unsafe { Slice::from_boxed_slice_unchecked(>>::default()) } } } -impl Debug for Slice { +impl Debug for Slice +where + EntityHash: TrustedBuildHasher, +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_tuple("Slice") .field(&self.0) @@ -450,40 +554,58 @@ impl Debug for Slice { } } -impl From<&Slice> for Box { - fn from(value: &Slice) -> Self { +impl From<&Slice> for Box> +where + EntityHash: TrustedBuildHasher, +{ + fn from(value: &Slice) -> Self { // SAFETY: This slice is a copy of a valid slice. unsafe { Slice::from_boxed_slice_unchecked(value.1.into()) } } } -impl Hash for Slice { +impl Hash for Slice +where + EntityHash: TrustedBuildHasher, +{ fn hash(&self, state: &mut H) { self.1.hash(state); } } -impl PartialOrd for Slice { +impl PartialOrd for Slice +where + EntityHash: TrustedBuildHasher, +{ fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) + self.1.partial_cmp(other) } } -impl Ord for Slice { +impl Ord for Slice +where + EntityHash: TrustedBuildHasher, +{ fn cmp(&self, other: &Self) -> Ordering { self.1.cmp(other) } } -impl PartialEq for Slice { +impl PartialEq for Slice +where + EntityHash: TrustedBuildHasher, +{ fn eq(&self, other: &Self) -> bool { self.1 == other.1 } } -impl Eq for Slice {} +impl Eq for Slice where EntityHash: TrustedBuildHasher {} -impl Index<(Bound, Bound)> for Slice { +impl Index<(Bound, Bound)> for Slice +where + EntityHash: TrustedBuildHasher, +{ type Output = Self; fn index(&self, key: (Bound, Bound)) -> &Self { // SAFETY: This a subslice of a valid slice. @@ -491,7 +613,10 @@ impl Index<(Bound, Bound)> for Slice { } } -impl Index> for Slice { +impl Index> for Slice +where + EntityHash: TrustedBuildHasher, +{ type Output = Self; fn index(&self, key: Range) -> &Self { // SAFETY: This a subslice of a valid slice. @@ -499,15 +624,21 @@ impl Index> for Slice { } } -impl Index> for Slice { - type Output = Slice; +impl Index> for Slice +where + EntityHash: TrustedBuildHasher, +{ + type Output = Slice; fn index(&self, key: RangeFrom) -> &Self { // SAFETY: This a subslice of a valid slice. unsafe { Self::from_slice_unchecked(self.1.index(key)) } } } -impl Index for Slice { +impl Index for Slice +where + EntityHash: TrustedBuildHasher, +{ type Output = Self; fn index(&self, key: RangeFull) -> &Self { // SAFETY: This a subslice of a valid slice. @@ -515,7 +646,10 @@ impl Index for Slice { } } -impl Index> for Slice { +impl Index> for Slice +where + EntityHash: TrustedBuildHasher, +{ type Output = Self; fn index(&self, key: RangeInclusive) -> &Self { // SAFETY: This a subslice of a valid slice. @@ -523,7 +657,10 @@ impl Index> for Slice { } } -impl Index> for Slice { +impl Index> for Slice +where + EntityHash: TrustedBuildHasher, +{ type Output = Self; fn index(&self, key: RangeTo) -> &Self { // SAFETY: This a subslice of a valid slice. @@ -531,7 +668,10 @@ impl Index> for Slice { } } -impl Index> for Slice { +impl Index> for Slice +where + EntityHash: TrustedBuildHasher, +{ type Output = Self; fn index(&self, key: RangeToInclusive) -> &Self { // SAFETY: This a subslice of a valid slice. @@ -539,137 +679,204 @@ impl Index> for Slice { } } -impl Index for Slice { - type Output = Entity; - fn index(&self, key: usize) -> &Entity { +impl Index for Slice +where + EntityHash: TrustedBuildHasher, +{ + type Output = K; + fn index(&self, key: usize) -> &K { self.1.index(key) } } -/// An iterator over the items of an [`EntityIndexSet`]. +/// An iterator over the items of an [`EntityEquivalentIndexSet`]. /// -/// This struct is created by the [`iter`] method on [`EntityIndexSet`]. See its documentation for more. +/// This struct is created by the [`iter`] method on [`EntityEquivalentIndexSet`]. See its documentation for more. /// -/// [`iter`]: EntityIndexSet::iter -pub struct Iter<'a, S = EntityHash>(set::Iter<'a, Entity>, PhantomData); +/// [`iter`]: EntityEquivalentIndexSet::iter +pub struct Iter<'a, K: TrustedEntityBorrow + Hash, S = EntityHash>( + set::Iter<'a, K>, + PhantomData, +) +where + EntityHash: TrustedBuildHasher; -impl<'a> Iter<'a> { +impl<'a, K: TrustedEntityBorrow + Hash> Iter<'a, K> +where + EntityHash: TrustedBuildHasher, +{ /// Returns the inner [`Iter`](set::Iter). - pub fn into_inner(self) -> set::Iter<'a, Entity> { + pub fn into_inner(self) -> set::Iter<'a, K> { self.0 } /// Returns a slice of the remaining entries in the iterator. /// /// Equivalent to [`set::Iter::as_slice`]. - pub fn as_slice(&self) -> &Slice { + pub fn as_slice(&self) -> &Slice { // SAFETY: The source IndexSet uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.as_slice()) } } } -impl<'a> Deref for Iter<'a> { - type Target = set::Iter<'a, Entity>; +impl<'a, K: TrustedEntityBorrow + Hash> Deref for Iter<'a, K> +where + EntityHash: TrustedBuildHasher, +{ + type Target = set::Iter<'a, K>; fn deref(&self) -> &Self::Target { &self.0 } } -impl<'a> Iterator for Iter<'a> { - type Item = &'a Entity; +impl<'a, K: TrustedEntityBorrow + Hash> Iterator for Iter<'a, K> +where + EntityHash: TrustedBuildHasher, +{ + type Item = &'a K; fn next(&mut self) -> Option { self.0.next() } } -impl DoubleEndedIterator for Iter<'_> { +impl DoubleEndedIterator for Iter<'_, K> +where + EntityHash: TrustedBuildHasher, +{ fn next_back(&mut self) -> Option { self.0.next_back() } } -impl ExactSizeIterator for Iter<'_> {} +impl ExactSizeIterator for Iter<'_, K> where + EntityHash: TrustedBuildHasher +{ +} -impl FusedIterator for Iter<'_> {} +impl FusedIterator for Iter<'_, K> where + EntityHash: TrustedBuildHasher +{ +} -impl Clone for Iter<'_> { +impl Clone for Iter<'_, K> +where + EntityHash: TrustedBuildHasher, +{ fn clone(&self) -> Self { Self(self.0.clone(), PhantomData) } } -impl Debug for Iter<'_> { +impl Debug for Iter<'_, K> +where + EntityHash: TrustedBuildHasher, +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_tuple("Iter").field(&self.0).field(&self.1).finish() } } -impl Default for Iter<'_> { +impl Default for Iter<'_, K> +where + EntityHash: TrustedBuildHasher, +{ fn default() -> Self { Self(Default::default(), PhantomData) } } -// SAFETY: Iter stems from a correctly behaving `IndexSet`. -unsafe impl EntitySetIterator for Iter<'_> {} +// SAFETY: Iter stems from a correctly behaving `IndexSet`. +unsafe impl EntitySetIterator for Iter<'_, K> where + EntityHash: TrustedBuildHasher +{ +} -/// Owning iterator over the items of an [`EntityIndexSet`]. +/// Owning iterator over the items of an [`EntityEquivalentIndexSet`]. /// -/// This struct is created by the [`into_iter`] method on [`EntityIndexSet`] (provided by the [`IntoIterator`] trait). See its documentation for more. +/// This struct is created by the [`into_iter`] method on [`EntityEquivalentIndexSet`] (provided by the [`IntoIterator`] trait). See its documentation for more. /// -/// [`into_iter`]: EntityIndexSet::into_iter -pub struct IntoIter(set::IntoIter, PhantomData); +/// [`into_iter`]: EntityEquivalentIndexSet::into_iter +pub struct IntoIter( + set::IntoIter, + PhantomData, +) +where + EntityHash: TrustedBuildHasher; -impl IntoIter { +impl IntoIter +where + EntityHash: TrustedBuildHasher, +{ /// Returns the inner [`IntoIter`](set::IntoIter). - pub fn into_inner(self) -> set::IntoIter { + pub fn into_inner(self) -> set::IntoIter { self.0 } /// Returns a slice of the remaining entries in the iterator. /// /// Equivalent to [`set::IntoIter::as_slice`]. - pub fn as_slice(&self) -> &Slice { + pub fn as_slice(&self) -> &Slice { // SAFETY: The source IndexSet uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.as_slice()) } } } -impl Deref for IntoIter { - type Target = set::IntoIter; +impl Deref for IntoIter +where + EntityHash: TrustedBuildHasher, +{ + type Target = set::IntoIter; fn deref(&self) -> &Self::Target { &self.0 } } -impl Iterator for IntoIter { - type Item = Entity; +impl Iterator for IntoIter +where + EntityHash: TrustedBuildHasher, +{ + type Item = K; fn next(&mut self) -> Option { self.0.next() } } -impl DoubleEndedIterator for IntoIter { +impl DoubleEndedIterator for IntoIter +where + EntityHash: TrustedBuildHasher, +{ fn next_back(&mut self) -> Option { self.0.next_back() } } -impl ExactSizeIterator for IntoIter {} +impl ExactSizeIterator for IntoIter where + EntityHash: TrustedBuildHasher +{ +} -impl FusedIterator for IntoIter {} +impl FusedIterator for IntoIter where + EntityHash: TrustedBuildHasher +{ +} -impl Clone for IntoIter { +impl Clone for IntoIter +where + EntityHash: TrustedBuildHasher, +{ fn clone(&self) -> Self { Self(self.0.clone(), PhantomData) } } -impl Debug for IntoIter { +impl Debug for IntoIter +where + EntityHash: TrustedBuildHasher, +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_tuple("IntoIter") .field(&self.0) @@ -678,64 +885,96 @@ impl Debug for IntoIter { } } -impl Default for IntoIter { +impl Default for IntoIter +where + EntityHash: TrustedBuildHasher, +{ fn default() -> Self { Self(Default::default(), PhantomData) } } -// SAFETY: IntoIter stems from a correctly behaving `IndexSet`. -unsafe impl EntitySetIterator for IntoIter {} +// SAFETY: IntoIter stems from a correctly behaving `IndexSet`. +unsafe impl EntitySetIterator for IntoIter where + EntityHash: TrustedBuildHasher +{ +} -/// A draining iterator over the items of an [`EntityIndexSet`]. +/// A draining iterator over the items of an [`EntityEquivalentIndexSet`]. /// -/// This struct is created by the [`drain`] method on [`EntityIndexSet`]. See its documentation for more. +/// This struct is created by the [`drain`] method on [`EntityEquivalentIndexSet`]. See its documentation for more. /// -/// [`drain`]: EntityIndexSet::drain -pub struct Drain<'a, S = EntityHash>(set::Drain<'a, Entity>, PhantomData); +/// [`drain`]: EntityEquivalentIndexSet::drain +pub struct Drain<'a, K: TrustedEntityBorrow + Hash, S = EntityHash>( + set::Drain<'a, K>, + PhantomData, +) +where + EntityHash: TrustedBuildHasher; -impl<'a> Drain<'a> { +impl<'a, K: TrustedEntityBorrow + Hash> Drain<'a, K> +where + EntityHash: TrustedBuildHasher, +{ /// Returns the inner [`Drain`](set::Drain). - pub fn into_inner(self) -> set::Drain<'a, Entity> { + pub fn into_inner(self) -> set::Drain<'a, K> { self.0 } /// Returns a slice of the remaining entries in the iterator.$ /// /// Equivalent to [`set::Drain::as_slice`]. - pub fn as_slice(&self) -> &Slice { + pub fn as_slice(&self) -> &Slice { // SAFETY: The source IndexSet uses EntityHash. unsafe { Slice::from_slice_unchecked(self.0.as_slice()) } } } -impl<'a> Deref for Drain<'a> { - type Target = set::Drain<'a, Entity>; +impl<'a, K: TrustedEntityBorrow + Hash> Deref for Drain<'a, K> +where + EntityHash: TrustedBuildHasher, +{ + type Target = set::Drain<'a, K>; fn deref(&self) -> &Self::Target { &self.0 } } -impl<'a> Iterator for Drain<'a> { - type Item = Entity; +impl<'a, K: TrustedEntityBorrow + Hash> Iterator for Drain<'a, K> +where + EntityHash: TrustedBuildHasher, +{ + type Item = K; fn next(&mut self) -> Option { self.0.next() } } -impl DoubleEndedIterator for Drain<'_> { +impl DoubleEndedIterator for Drain<'_, K> +where + EntityHash: TrustedBuildHasher, +{ fn next_back(&mut self) -> Option { self.0.next_back() } } -impl ExactSizeIterator for Drain<'_> {} +impl ExactSizeIterator for Drain<'_, K> where + EntityHash: TrustedBuildHasher +{ +} -impl FusedIterator for Drain<'_> {} +impl FusedIterator for Drain<'_, K> where + EntityHash: TrustedBuildHasher +{ +} -impl Debug for Drain<'_> { +impl Debug for Drain<'_, K> +where + EntityHash: TrustedBuildHasher, +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_tuple("Drain") .field(&self.0) @@ -744,23 +983,35 @@ impl Debug for Drain<'_> { } } -// SAFETY: Drain stems from a correctly behaving `IndexSet`. -unsafe impl EntitySetIterator for Drain<'_> {} +// SAFETY: Drain stems from a correctly behaving `IndexSet`. +unsafe impl EntitySetIterator for Drain<'_, K> where + EntityHash: TrustedBuildHasher +{ +} -// SAFETY: Difference stems from two correctly behaving `IndexSet`s. -unsafe impl EntitySetIterator for set::Difference<'_, Entity, EntityHash> {} +// SAFETY: Difference stems from two correctly behaving `IndexSet`s. +unsafe impl EntitySetIterator + for set::Difference<'_, K, EntityHash> +{ +} -// SAFETY: Intersection stems from two correctly behaving `IndexSet`s. -unsafe impl EntitySetIterator for set::Intersection<'_, Entity, EntityHash> {} +// SAFETY: Intersection stems from two correctly behaving `IndexSet`s. +unsafe impl EntitySetIterator + for set::Intersection<'_, K, EntityHash> +{ +} -// SAFETY: SymmetricDifference stems from two correctly behaving `IndexSet`s. -unsafe impl EntitySetIterator for set::SymmetricDifference<'_, Entity, EntityHash, EntityHash> {} +// SAFETY: SymmetricDifference stems from two correctly behaving `IndexSet`s. +unsafe impl EntitySetIterator + for set::SymmetricDifference<'_, K, EntityHash, EntityHash> +{ +} -// SAFETY: Union stems from two correctly behaving `IndexSet`s. -unsafe impl EntitySetIterator for set::Union<'_, Entity, EntityHash> {} +// SAFETY: Union stems from two correctly behaving `IndexSet`s. +unsafe impl EntitySetIterator for set::Union<'_, K, EntityHash> {} -// SAFETY: Splice stems from a correctly behaving `IndexSet`s. -unsafe impl> EntitySetIterator - for set::Splice<'_, I, Entity, EntityHash> +// SAFETY: Splice stems from a correctly behaving `IndexSet`s. +unsafe impl> EntitySetIterator + for set::Splice<'_, I, K, EntityHash> { } diff --git a/crates/bevy_ecs/src/relationship/relationship_source_collection.rs b/crates/bevy_ecs/src/relationship/relationship_source_collection.rs index c3748e46a7eab..8cc620f34a1dd 100644 --- a/crates/bevy_ecs/src/relationship/relationship_source_collection.rs +++ b/crates/bevy_ecs/src/relationship/relationship_source_collection.rs @@ -85,7 +85,7 @@ impl RelationshipSourceCollection for Vec { } impl RelationshipSourceCollection for EntityHashSet { - type SourceIter<'a> = core::iter::Copied>; + type SourceIter<'a> = core::iter::Copied>; fn with_capacity(capacity: usize) -> Self { EntityHashSet::with_capacity(capacity) diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index ea60f42667815..178c9e008621c 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -844,7 +844,7 @@ impl Default for SpecializedPrepassMaterialPipelineCache { impl Default for SpecializedPrepassMaterialViewPipelineCache { fn default() -> Self { Self { - map: HashMap::default(), + map: MainEntityHashMap::default(), marker: PhantomData, } } diff --git a/crates/bevy_render/src/sync_world.rs b/crates/bevy_render/src/sync_world.rs index 4f21e22bf9b28..84e178c83180e 100644 --- a/crates/bevy_render/src/sync_world.rs +++ b/crates/bevy_render/src/sync_world.rs @@ -1,6 +1,8 @@ use bevy_app::Plugin; use bevy_derive::{Deref, DerefMut}; -use bevy_ecs::entity::EntityHash; +use bevy_ecs::entity::hash_map::EntityEquivalentHashMap; +use bevy_ecs::entity::hash_set::EntityEquivalentHashSet; +use bevy_ecs::entity::{EntityHash, TrustedBuildHasher}; use bevy_ecs::{ component::Component, entity::{Entity, EntityBorrow, TrustedEntityBorrow}, @@ -11,7 +13,7 @@ use bevy_ecs::{ system::{Local, Query, ResMut, SystemState}, world::{Mut, OnAdd, OnRemove, World}, }; -use bevy_platform_support::collections::{HashMap, HashSet}; + use bevy_reflect::{std_traits::ReflectDefault, Reflect}; /// A plugin that synchronizes entities with [`SyncToRenderWorld`] between the main world and the render world. @@ -150,6 +152,9 @@ impl EntityBorrow for RenderEntity { // SAFETY: RenderEntity is a newtype around Entity that derives its comparison traits. unsafe impl TrustedEntityBorrow for RenderEntity {} +// SAFETY: EntityHasher hashes `Entity` deterministically. +unsafe impl TrustedBuildHasher for EntityHash {} + /// Component added on the render world entities to keep track of the corresponding main world entity. /// /// Can also be used as a newtype wrapper for main world entities. @@ -177,11 +182,14 @@ impl EntityBorrow for MainEntity { // SAFETY: RenderEntity is a newtype around Entity that derives its comparison traits. unsafe impl TrustedEntityBorrow for MainEntity {} +// SAFETY: EntityHasher hashes `Entity` deterministically. +unsafe impl TrustedBuildHasher for EntityHash {} + /// A [`HashMap`] pre-configured to use [`EntityHash`] hashing with a [`MainEntity`]. -pub type MainEntityHashMap = HashMap; +pub type MainEntityHashMap = EntityEquivalentHashMap; /// A [`HashSet`] pre-configured to use [`EntityHash`] hashing with a [`MainEntity`].. -pub type MainEntityHashSet = HashSet; +pub type MainEntityHashSet = EntityEquivalentHashSet; /// Marker component that indicates that its entity needs to be despawned at the end of the frame. #[derive(Component, Copy, Clone, Debug, Default, Reflect)] diff --git a/crates/bevy_sprite/src/mesh2d/material.rs b/crates/bevy_sprite/src/mesh2d/material.rs index 81ad7a9e3ee34..71a87b6fbf3e4 100644 --- a/crates/bevy_sprite/src/mesh2d/material.rs +++ b/crates/bevy_sprite/src/mesh2d/material.rs @@ -19,7 +19,6 @@ use bevy_ecs::{ system::{lifetimeless::SRes, SystemParamItem}, }; use bevy_math::FloatOrd; -use bevy_platform_support::collections::HashMap; use bevy_reflect::{prelude::ReflectDefault, Reflect}; use bevy_render::render_phase::{DrawFunctionId, InputUniformIndex}; use bevy_render::render_resource::CachedRenderPipelineId; @@ -619,7 +618,7 @@ pub struct SpecializedMaterial2dViewPipelineCache { impl Default for SpecializedMaterial2dPipelineCache { fn default() -> Self { Self { - map: HashMap::default(), + map: MainEntityHashMap::default(), marker: PhantomData, } } @@ -628,7 +627,7 @@ impl Default for SpecializedMaterial2dPipelineCache { impl Default for SpecializedMaterial2dViewPipelineCache { fn default() -> Self { Self { - map: HashMap::default(), + map: MainEntityHashMap::default(), marker: PhantomData, } } From 8bb8952a2c456981350ce1cb4b4161e0366d0759 Mon Sep 17 00:00:00 2001 From: Victoron <59878206+Victoronz@users.noreply.github.com> Date: Wed, 19 Mar 2025 02:41:30 +0100 Subject: [PATCH 2/4] adjust doc link --- crates/bevy_ecs/src/entity/hash.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/entity/hash.rs b/crates/bevy_ecs/src/entity/hash.rs index 8ba65bccd0b94..9cfeba1aac396 100644 --- a/crates/bevy_ecs/src/entity/hash.rs +++ b/crates/bevy_ecs/src/entity/hash.rs @@ -55,7 +55,7 @@ unsafe impl TrustedBuildHasher> for EntityHash unsafe impl TrustedBuildHasher> for EntityHash {} /// A very fast hash that is only designed to work on generational indices -/// like [`Entity`](super::Entity). It will panic if attempting to hash a type containing +/// like [`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 From bead56880fe60de8792e909c6b0fd1f67e535b4c Mon Sep 17 00:00:00 2001 From: Victoron <59878206+Victoronz@users.noreply.github.com> Date: Wed, 19 Mar 2025 02:58:20 +0100 Subject: [PATCH 3/4] more doc link fixes --- crates/bevy_render/src/sync_world.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/bevy_render/src/sync_world.rs b/crates/bevy_render/src/sync_world.rs index 84e178c83180e..9e8ba43b494b2 100644 --- a/crates/bevy_render/src/sync_world.rs +++ b/crates/bevy_render/src/sync_world.rs @@ -186,9 +186,13 @@ unsafe impl TrustedEntityBorrow for MainEntity {} unsafe impl TrustedBuildHasher for EntityHash {} /// A [`HashMap`] pre-configured to use [`EntityHash`] hashing with a [`MainEntity`]. +/// +/// [`HashMap`]: `bevy_platform_support::collections::HashMap` pub type MainEntityHashMap = EntityEquivalentHashMap; -/// A [`HashSet`] pre-configured to use [`EntityHash`] hashing with a [`MainEntity`].. +/// A [`HashSet`] pre-configured to use [`EntityHash`] hashing with a [`MainEntity`]. +/// +/// [`HashSet`]: `bevy_platform_support::collections::HashSet` pub type MainEntityHashSet = EntityEquivalentHashSet; /// Marker component that indicates that its entity needs to be despawned at the end of the frame. From ee43371c730b9100f6ce82ef59ebecdf6de216f3 Mon Sep 17 00:00:00 2001 From: Victoron <59878206+Victoronz@users.noreply.github.com> Date: Wed, 19 Mar 2025 03:13:51 +0100 Subject: [PATCH 4/4] remove doc spaces --- crates/bevy_render/src/sync_world.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_render/src/sync_world.rs b/crates/bevy_render/src/sync_world.rs index 9e8ba43b494b2..20edbfbcc0fa0 100644 --- a/crates/bevy_render/src/sync_world.rs +++ b/crates/bevy_render/src/sync_world.rs @@ -186,12 +186,12 @@ unsafe impl TrustedEntityBorrow for MainEntity {} unsafe impl TrustedBuildHasher for EntityHash {} /// A [`HashMap`] pre-configured to use [`EntityHash`] hashing with a [`MainEntity`]. -/// +/// /// [`HashMap`]: `bevy_platform_support::collections::HashMap` pub type MainEntityHashMap = EntityEquivalentHashMap; /// A [`HashSet`] pre-configured to use [`EntityHash`] hashing with a [`MainEntity`]. -/// +/// /// [`HashSet`]: `bevy_platform_support::collections::HashSet` pub type MainEntityHashSet = EntityEquivalentHashSet;