diff --git a/crates/bevy_ecs/src/entity/index_map.rs b/crates/bevy_ecs/src/entity/index_map.rs new file mode 100644 index 0000000000..80abf72e7f --- /dev/null +++ b/crates/bevy_ecs/src/entity/index_map.rs @@ -0,0 +1,541 @@ +use core::{ + fmt::{self, Debug, Formatter}, + hash::BuildHasher, + iter::FusedIterator, + marker::PhantomData, + ops::{Deref, DerefMut, Index, IndexMut, RangeBounds}, +}; + +#[cfg(feature = "bevy_reflect")] +use bevy_reflect::Reflect; +use indexmap::map::{self, IndexMap}; + +use super::{Entity, EntityHash, EntitySetIterator, TrustedEntityBorrow}; + +/// A [`IndexMap`] pre-configured to use [`EntityHash`] hashing. +#[cfg_attr(feature = "bevy_reflect", derive(Reflect))] +#[derive(Debug, Clone)] +pub struct EntityIndexMap(pub(crate) IndexMap); + +impl EntityIndexMap { + /// Creates an empty `EntityIndexMap`. + /// + /// Equivalent to [`IndexMap::with_hasher(EntityHash)`]. + /// + /// [`IndexMap::with_hasher(EntityHash)`]: IndexMap::with_hasher + pub fn new() -> Self { + Self(IndexMap::with_hasher(EntityHash)) + } + + /// Creates an empty `EntityIndexMap` with the specified capacity. + /// + /// Equivalent to [`IndexMap::with_capacity_and_hasher(n, EntityHash)`]. + /// + /// [`IndexMap:with_capacity_and_hasher(n, EntityHash)`]: IndexMap::with_capacity_and_hasher + pub fn with_capacity(n: usize) -> Self { + Self(IndexMap::with_capacity_and_hasher(n, EntityHash)) + } + + /// Returns the inner [`IndexMap`]. + pub fn into_inner(self) -> IndexMap { + self.0 + } + + /// Return an iterator over the key-value pairs of the map, in their order. + /// + /// Equivalent to [`IndexMap::iter`]. + pub fn iter(&self) -> Iter<'_, 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> { + IterMut(self.0.iter_mut(), PhantomData) + } + + /// Clears the `IndexMap` in the given index range, returning those + /// key-value pairs as a drain iterator. + /// + /// Equivalent to [`IndexMap::drain`]. + pub fn drain>(&mut self, range: R) -> Drain<'_, 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> { + 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 { + IntoKeys(self.0.into_keys(), PhantomData) + } +} + +impl Default for EntityIndexMap { + fn default() -> Self { + Self(Default::default()) + } +} + +impl Deref for EntityIndexMap { + type Target = IndexMap; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for EntityIndexMap { + 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) { + self.0.extend(iter); + } +} + +impl Extend<(Entity, V)> for EntityIndexMap { + fn extend>(&mut self, iter: T) { + self.0.extend(iter); + } +} + +impl From<[(Entity, V); N]> for EntityIndexMap { + fn from(value: [(Entity, V); N]) -> Self { + Self(IndexMap::from_iter(value)) + } +} + +impl FromIterator<(Entity, V)> for EntityIndexMap { + fn from_iter>(iterable: I) -> Self { + Self(IndexMap::from_iter(iterable)) + } +} + +impl Index<&Q> for EntityIndexMap { + type Output = V; + fn index(&self, key: &Q) -> &V { + self.0.index(&key.entity()) + } +} + +impl Index for EntityIndexMap { + type Output = V; + fn index(&self, key: usize) -> &V { + self.0.index(key) + } +} + +impl IndexMut<&Q> for EntityIndexMap { + fn index_mut(&mut self, key: &Q) -> &mut V { + self.0.index_mut(&key.entity()) + } +} + +impl IndexMut for EntityIndexMap { + 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>; + + 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>; + + fn into_iter(self) -> Self::IntoIter { + IterMut(self.0.iter_mut(), PhantomData) + } +} + +impl IntoIterator for EntityIndexMap { + type Item = (Entity, V); + type IntoIter = IntoIter; + + fn into_iter(self) -> Self::IntoIter { + IntoIter(self.0.into_iter(), PhantomData) + } +} + +impl PartialEq> for EntityIndexMap +where + V1: PartialEq, + S2: BuildHasher, +{ + fn eq(&self, other: &IndexMap) -> bool { + self.0.eq(other) + } +} + +impl PartialEq> for EntityIndexMap +where + V1: PartialEq, +{ + fn eq(&self, other: &EntityIndexMap) -> bool { + self.0.eq(other) + } +} + +impl Eq for EntityIndexMap {} + +/// An iterator over the entries of an [`EntityIndexMap`]. +/// +/// This `struct` is created by the [`EntityIndexMap::iter`] method. +/// See its documentation for more. +pub struct Iter<'a, V, S = EntityHash>(map::Iter<'a, Entity, V>, PhantomData); + +impl<'a, V> Iter<'a, V> { + /// Returns the inner [`Iter`](map::Iter). + pub fn into_inner(self) -> map::Iter<'a, Entity, V> { + self.0 + } +} + +impl<'a, V> Deref for Iter<'a, V> { + type Target = map::Iter<'a, Entity, V>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl<'a, V> Iterator for Iter<'a, V> { + type Item = (&'a Entity, &'a V); + + fn next(&mut self) -> Option { + self.0.next() + } +} + +impl DoubleEndedIterator for Iter<'_, V> { + fn next_back(&mut self) -> Option { + self.0.next_back() + } +} + +impl ExactSizeIterator for Iter<'_, V> {} + +impl FusedIterator for Iter<'_, V> {} + +impl Clone for Iter<'_, V> { + fn clone(&self) -> Self { + Self(self.0.clone(), PhantomData) + } +} + +impl Debug for Iter<'_, V> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_tuple("Iter").field(&self.0).field(&self.1).finish() + } +} + +impl Default for Iter<'_, V> { + fn default() -> Self { + Self(Default::default(), PhantomData) + } +} + +/// A mutable iterator over the entries of an [`EntityIndexMap`]. +/// +/// This `struct` is created by the [`EntityIndexMap::iter_mut`] method. +/// See its documentation for more. +pub struct IterMut<'a, V, S = EntityHash>(map::IterMut<'a, Entity, V>, PhantomData); + +impl<'a, V> IterMut<'a, V> { + /// Returns the inner [`IterMut`](map::IterMut). + pub fn into_inner(self) -> map::IterMut<'a, Entity, V> { + self.0 + } +} + +impl<'a, V> Deref for IterMut<'a, V> { + type Target = map::IterMut<'a, Entity, V>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl<'a, V> Iterator for IterMut<'a, V> { + type Item = (&'a Entity, &'a mut V); + + fn next(&mut self) -> Option { + self.0.next() + } +} + +impl DoubleEndedIterator for IterMut<'_, V> { + fn next_back(&mut self) -> Option { + self.0.next_back() + } +} + +impl ExactSizeIterator for IterMut<'_, V> {} + +impl FusedIterator for IterMut<'_, V> {} + +impl Debug for IterMut<'_, V> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_tuple("IterMut") + .field(&self.0) + .field(&self.1) + .finish() + } +} + +impl Default for IterMut<'_, V> { + fn default() -> Self { + Self(Default::default(), PhantomData) + } +} + +/// An owning iterator over the entries of an [`IndexMap`]. +/// +/// 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); + +impl IntoIter { + /// Returns the inner [`IntoIter`](map::IntoIter). + pub fn into_inner(self) -> map::IntoIter { + self.0 + } +} + +impl Deref for IntoIter { + type Target = map::IntoIter; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Iterator for IntoIter { + type Item = (Entity, V); + + fn next(&mut self) -> Option { + self.0.next() + } +} + +impl DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option { + self.0.next_back() + } +} + +impl ExactSizeIterator for IntoIter {} + +impl FusedIterator for IntoIter {} + +impl Clone for IntoIter { + fn clone(&self) -> Self { + Self(self.0.clone(), PhantomData) + } +} + +impl Debug for IntoIter { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_tuple("IntoIter") + .field(&self.0) + .field(&self.1) + .finish() + } +} + +impl Default for IntoIter { + fn default() -> Self { + Self(Default::default(), PhantomData) + } +} + +/// A draining iterator over the entries of an [`EntityIndexMap`]. +/// +/// This `struct` is created by the [`EntityIndexMap::drain`] method. +/// See its documentation for more. +pub struct Drain<'a, V, S = EntityHash>(map::Drain<'a, Entity, V>, PhantomData); + +impl<'a, V> Drain<'a, V> { + /// Returns the inner [`Drain`](map::Drain). + pub fn into_inner(self) -> map::Drain<'a, Entity, V> { + self.0 + } +} + +impl<'a, V> Deref for Drain<'a, V> { + type Target = map::Drain<'a, Entity, V>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Iterator for Drain<'_, V> { + type Item = (Entity, V); + + fn next(&mut self) -> Option { + self.0.next() + } +} + +impl DoubleEndedIterator for Drain<'_, V> { + fn next_back(&mut self) -> Option { + self.0.next_back() + } +} + +impl ExactSizeIterator for Drain<'_, V> {} + +impl FusedIterator for Drain<'_, V> {} + +impl Debug for Drain<'_, V> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_tuple("Drain") + .field(&self.0) + .field(&self.1) + .finish() + } +} + +/// An iterator over the keys of an [`EntityIndexMap`]. +/// +/// This `struct` is created by the [`EntityIndexMap::keys`] method. +/// See its documentation for more. +pub struct Keys<'a, V, S = EntityHash>(map::Keys<'a, Entity, V>, PhantomData); + +impl<'a, V> Keys<'a, V> { + /// Returns the inner [`Keys`](map::Keys). + pub fn into_inner(self) -> map::Keys<'a, Entity, V> { + self.0 + } +} + +impl<'a, V, S> Deref for Keys<'a, V, S> { + type Target = map::Keys<'a, Entity, V>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl<'a, V> Iterator for Keys<'a, V> { + type Item = &'a Entity; + + fn next(&mut self) -> Option { + self.0.next() + } +} + +impl DoubleEndedIterator for Keys<'_, V> { + fn next_back(&mut self) -> Option { + self.0.next_back() + } +} + +impl ExactSizeIterator for Keys<'_, V> {} + +impl FusedIterator for Keys<'_, V> {} + +impl Index for Keys<'_, V> { + type Output = Entity; + + fn index(&self, index: usize) -> &Entity { + self.0.index(index) + } +} + +impl Clone for Keys<'_, V> { + fn clone(&self) -> Self { + Self(self.0.clone(), PhantomData) + } +} + +impl Debug for Keys<'_, V> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_tuple("Keys").field(&self.0).field(&self.1).finish() + } +} + +impl Default for Keys<'_, V> { + fn default() -> Self { + Self(Default::default(), PhantomData) + } +} + +// SAFETY: Keys stems from a correctly behaving `IndexMap`. +unsafe impl EntitySetIterator for Keys<'_, V> {} + +/// An owning iterator over the keys of an [`EntityIndexMap`]. +/// +/// This `struct` is created by the [`EntityIndexMap::into_keys`] method. +/// See its documentation for more. +pub struct IntoKeys(map::IntoKeys, PhantomData); + +impl IntoKeys { + /// Returns the inner [`IntoKeys`](map::IntoKeys). + pub fn into_inner(self) -> map::IntoKeys { + self.0 + } +} + +impl Deref for IntoKeys { + type Target = map::IntoKeys; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Iterator for IntoKeys { + type Item = Entity; + + fn next(&mut self) -> Option { + self.0.next() + } +} + +impl DoubleEndedIterator for IntoKeys { + fn next_back(&mut self) -> Option { + self.0.next_back() + } +} + +impl ExactSizeIterator for IntoKeys {} + +impl FusedIterator for IntoKeys {} + +impl Debug for IntoKeys { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_tuple("IntoKeys") + .field(&self.0) + .field(&self.1) + .finish() + } +} + +impl Default for IntoKeys { + fn default() -> Self { + Self(Default::default(), PhantomData) + } +} + +// SAFETY: IntoKeys stems from a correctly behaving `IndexMap`. +unsafe impl EntitySetIterator for IntoKeys {} diff --git a/crates/bevy_ecs/src/entity/index_set.rs b/crates/bevy_ecs/src/entity/index_set.rs new file mode 100644 index 0000000000..60825727cf --- /dev/null +++ b/crates/bevy_ecs/src/entity/index_set.rs @@ -0,0 +1,364 @@ +use core::{ + fmt::{self, Debug, Formatter}, + hash::BuildHasher, + iter::FusedIterator, + marker::PhantomData, + ops::{BitAnd, BitOr, BitXor, Deref, DerefMut, Index, RangeBounds, Sub}, +}; + +use indexmap::set::{self, IndexSet}; + +use super::{Entity, EntityHash, EntitySetIterator}; + +/// An [`IndexSet`] pre-configured to use [`EntityHash`] hashing. +#[derive(Debug, Clone, Default)] +pub struct EntityIndexSet(pub(crate) IndexSet); + +impl EntityIndexSet { + /// Creates an empty `EntityIndexSet`. + /// + /// Equivalent to [`IndexSet::with_hasher(EntityHash)`]. + /// + /// [`IndexSet::with_hasher(EntityHash)`]: IndexSet::with_hasher + pub fn new() -> Self { + Self(IndexSet::with_hasher(EntityHash)) + } + + /// Creates an empty `EntityIndexSet` with the specified capacity. + /// + /// Equivalent to [`IndexSet::with_capacity_and_hasher(n, EntityHash)`]. + /// + /// [`IndexSet::with_capacity_and_hasher(n, EntityHash)`]: IndexSet::with_capacity_and_hasher + pub fn with_capacity(n: usize) -> Self { + Self(IndexSet::with_capacity_and_hasher(n, EntityHash)) + } + + /// Returns the inner [`IndexSet`]. + pub fn into_inner(self) -> IndexSet { + self.0 + } + + /// Clears the `IndexSet` in the given index range, returning those values + /// as a drain iterator. + /// + /// Equivalent to [`IndexSet::drain`]. + pub fn drain>(&mut self, range: R) -> Drain<'_> { + Drain(self.0.drain(range), PhantomData) + } + + /// Return an iterator over the values of the set, in their order. + /// + /// Equivalent to [`IndexSet::iter`]. + pub fn iter(&self) -> Iter<'_> { + Iter(self.0.iter(), PhantomData) + } +} + +impl Deref for EntityIndexSet { + type Target = IndexSet; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for EntityIndexSet { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl<'a> IntoIterator for &'a EntityIndexSet { + type Item = &'a Entity; + + type IntoIter = Iter<'a>; + + fn into_iter(self) -> Self::IntoIter { + Iter((&self.0).into_iter(), PhantomData) + } +} + +impl IntoIterator for EntityIndexSet { + type Item = Entity; + + type IntoIter = IntoIter; + + fn into_iter(self) -> Self::IntoIter { + IntoIter(self.0.into_iter(), PhantomData) + } +} + +impl BitAnd for &EntityIndexSet { + type Output = EntityIndexSet; + + fn bitand(self, rhs: Self) -> Self::Output { + EntityIndexSet(self.0.bitand(&rhs.0)) + } +} + +impl BitOr for &EntityIndexSet { + type Output = EntityIndexSet; + + fn bitor(self, rhs: Self) -> Self::Output { + EntityIndexSet(self.0.bitor(&rhs.0)) + } +} + +impl BitXor for &EntityIndexSet { + type Output = EntityIndexSet; + + fn bitxor(self, rhs: Self) -> Self::Output { + EntityIndexSet(self.0.bitxor(&rhs.0)) + } +} + +impl Sub for &EntityIndexSet { + type Output = EntityIndexSet; + + fn sub(self, rhs: Self) -> Self::Output { + EntityIndexSet(self.0.sub(&rhs.0)) + } +} + +impl<'a> Extend<&'a Entity> for EntityIndexSet { + fn extend>(&mut self, iter: T) { + self.0.extend(iter); + } +} + +impl Extend for EntityIndexSet { + fn extend>(&mut self, iter: T) { + self.0.extend(iter); + } +} + +impl From<[Entity; N]> for EntityIndexSet { + fn from(value: [Entity; N]) -> Self { + Self(IndexSet::from_iter(value)) + } +} + +impl FromIterator for EntityIndexSet { + fn from_iter>(iterable: I) -> Self { + Self(IndexSet::from_iter(iterable)) + } +} + +impl PartialEq> for EntityIndexSet +where + S2: BuildHasher, +{ + fn eq(&self, other: &IndexSet) -> bool { + self.0.eq(other) + } +} + +impl PartialEq for EntityIndexSet { + fn eq(&self, other: &EntityIndexSet) -> bool { + self.0.eq(other) + } +} + +impl Eq for EntityIndexSet {} + +impl Index for EntityIndexSet { + type Output = Entity; + fn index(&self, key: usize) -> &Entity { + self.0.index(key) + } +} + +/// An iterator over the items of an [`EntityIndexSet`]. +/// +/// This struct is created by the [`iter`] method on [`EntityIndexSet`]. See its documentation for more. +/// +/// [`iter`]: EntityIndexSet::iter +pub struct Iter<'a, S = EntityHash>(set::Iter<'a, Entity>, PhantomData); + +impl<'a> Iter<'a> { + /// Returns the inner [`Iter`](set::Iter). + pub fn into_inner(self) -> set::Iter<'a, Entity> { + self.0 + } +} + +impl<'a> Deref for Iter<'a> { + type Target = set::Iter<'a, Entity>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl<'a> Iterator for Iter<'a> { + type Item = &'a Entity; + + fn next(&mut self) -> Option { + self.0.next() + } +} + +impl DoubleEndedIterator for Iter<'_> { + fn next_back(&mut self) -> Option { + self.0.next_back() + } +} + +impl ExactSizeIterator for Iter<'_> {} + +impl FusedIterator for Iter<'_> {} + +impl Clone for Iter<'_> { + fn clone(&self) -> Self { + Self(self.0.clone(), PhantomData) + } +} + +impl Debug for Iter<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_tuple("Iter").field(&self.0).field(&self.1).finish() + } +} + +impl Default for Iter<'_> { + fn default() -> Self { + Self(Default::default(), PhantomData) + } +} + +// SAFETY: Iter stems from a correctly behaving `IndexSet`. +unsafe impl EntitySetIterator for Iter<'_> {} + +/// Owning iterator over the items of an [`EntityIndexSet`]. +/// +/// This struct is created by the [`into_iter`] method on [`EntityIndexSet`] (provided by the [`IntoIterator`] trait). See its documentation for more. +/// +/// [`into_iter`]: EntityIndexSet::into_iter +pub struct IntoIter(set::IntoIter, PhantomData); + +impl IntoIter { + /// Returns the inner [`IntoIter`](set::IntoIter). + pub fn into_inner(self) -> set::IntoIter { + self.0 + } +} + +impl Deref for IntoIter { + type Target = set::IntoIter; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Iterator for IntoIter { + type Item = Entity; + + fn next(&mut self) -> Option { + self.0.next() + } +} + +impl DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option { + self.0.next_back() + } +} + +impl ExactSizeIterator for IntoIter {} + +impl FusedIterator for IntoIter {} + +impl Clone for IntoIter { + fn clone(&self) -> Self { + Self(self.0.clone(), PhantomData) + } +} + +impl Debug for IntoIter { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_tuple("IntoIter") + .field(&self.0) + .field(&self.1) + .finish() + } +} + +impl Default for IntoIter { + fn default() -> Self { + Self(Default::default(), PhantomData) + } +} + +// SAFETY: IntoIter stems from a correctly behaving `IndexSet`. +unsafe impl EntitySetIterator for IntoIter {} + +/// A draining iterator over the items of an [`EntityIndexSet`]. +/// +/// This struct is created by the [`drain`] method on [`EntityIndexSet`]. See its documentation for more. +/// +/// [`drain`]: EntityIndexSet::drain +pub struct Drain<'a, S = EntityHash>(set::Drain<'a, Entity>, PhantomData); + +impl<'a> Drain<'a> { + /// Returns the inner [`Drain`](set::Drain). + pub fn into_inner(self) -> set::Drain<'a, Entity> { + self.0 + } +} + +impl<'a> Deref for Drain<'a> { + type Target = set::Drain<'a, Entity>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl<'a> Iterator for Drain<'a> { + type Item = Entity; + + fn next(&mut self) -> Option { + self.0.next() + } +} + +impl DoubleEndedIterator for Drain<'_> { + fn next_back(&mut self) -> Option { + self.0.next_back() + } +} + +impl ExactSizeIterator for Drain<'_> {} + +impl FusedIterator for Drain<'_> {} + +impl Debug for Drain<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_tuple("Drain") + .field(&self.0) + .field(&self.1) + .finish() + } +} + +// SAFETY: Drain stems from a correctly behaving `IndexSet`. +unsafe impl EntitySetIterator for Drain<'_> {} + +// SAFETY: Difference stems from two correctly behaving `IndexSet`s. +unsafe impl EntitySetIterator for set::Difference<'_, Entity, EntityHash> {} + +// SAFETY: Intersection stems from two correctly behaving `IndexSet`s. +unsafe impl EntitySetIterator for set::Intersection<'_, Entity, EntityHash> {} + +// SAFETY: SymmetricDifference stems from two correctly behaving `IndexSet`s. +unsafe impl EntitySetIterator for set::SymmetricDifference<'_, Entity, EntityHash, EntityHash> {} + +// SAFETY: Union stems from two correctly behaving `IndexSet`s. +unsafe impl EntitySetIterator for set::Union<'_, Entity, EntityHash> {} + +// SAFETY: Splice stems from a correctly behaving `IndexSet`s. +unsafe impl> EntitySetIterator + for set::Splice<'_, I, Entity, EntityHash> +{ +} diff --git a/crates/bevy_ecs/src/entity/mod.rs b/crates/bevy_ecs/src/entity/mod.rs index 4666ac2c9d..3fa63d37fa 100644 --- a/crates/bevy_ecs/src/entity/mod.rs +++ b/crates/bevy_ecs/src/entity/mod.rs @@ -56,6 +56,12 @@ pub use hash::*; pub mod hash_map; pub mod hash_set; +mod index_map; +mod index_set; + +pub use index_map::EntityIndexMap; +pub use index_set::EntityIndexSet; + use crate::{ archetype::{ArchetypeId, ArchetypeRow}, identifier::{