implement EntityIndexMap/Set (#17449)
# Objective We do not have `EntityIndexMap`/`EntityIndexSet`. Usual `HashMap`s/`HashSet`s do not guarantee any order, which can be awkward for some use cases. The `indexmap` versions remember insertion order, which then also becomes their iteration order. They can be thought of as a `HashTable` + `Vec`, which means fast iteration and removal, indexing by index (not just key), and slicing! Performance should otherwise be comparable. ## Solution Because `indexmap` is structured to mirror `hashbrown`, it suffers the same issue of not having the `Hasher` generic on their iterators. #16912 solved this issue for `EntityHashMap`/`EntityHashSet` with a wrapper around the hashbrown version, so this PR does the same. Hopefully these wrappers can be removed again in the future by having `hashbrown`/`indexmap` adopt that generic in their iterators themselves!
This commit is contained in:
parent
40007cdb2e
commit
39a1e2b488
541
crates/bevy_ecs/src/entity/index_map.rs
Normal file
541
crates/bevy_ecs/src/entity/index_map.rs
Normal file
@ -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<V>(pub(crate) IndexMap<Entity, V, EntityHash>);
|
||||
|
||||
impl<V> EntityIndexMap<V> {
|
||||
/// 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<Entity, V, EntityHash> {
|
||||
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<R: RangeBounds<usize>>(&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<V> {
|
||||
IntoKeys(self.0.into_keys(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Default for EntityIndexMap<V> {
|
||||
fn default() -> Self {
|
||||
Self(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Deref for EntityIndexMap<V> {
|
||||
type Target = IndexMap<Entity, V, EntityHash>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> DerefMut for EntityIndexMap<V> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V: Copy> Extend<(&'a Entity, &'a V)> for EntityIndexMap<V> {
|
||||
fn extend<T: IntoIterator<Item = (&'a Entity, &'a V)>>(&mut self, iter: T) {
|
||||
self.0.extend(iter);
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Extend<(Entity, V)> for EntityIndexMap<V> {
|
||||
fn extend<T: IntoIterator<Item = (Entity, V)>>(&mut self, iter: T) {
|
||||
self.0.extend(iter);
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, const N: usize> From<[(Entity, V); N]> for EntityIndexMap<V> {
|
||||
fn from(value: [(Entity, V); N]) -> Self {
|
||||
Self(IndexMap::from_iter(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> FromIterator<(Entity, V)> for EntityIndexMap<V> {
|
||||
fn from_iter<I: IntoIterator<Item = (Entity, V)>>(iterable: I) -> Self {
|
||||
Self(IndexMap::from_iter(iterable))
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, Q: TrustedEntityBorrow + ?Sized> Index<&Q> for EntityIndexMap<V> {
|
||||
type Output = V;
|
||||
fn index(&self, key: &Q) -> &V {
|
||||
self.0.index(&key.entity())
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<usize> for EntityIndexMap<V> {
|
||||
type Output = V;
|
||||
fn index(&self, key: usize) -> &V {
|
||||
self.0.index(key)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, Q: TrustedEntityBorrow + ?Sized> IndexMut<&Q> for EntityIndexMap<V> {
|
||||
fn index_mut(&mut self, key: &Q) -> &mut V {
|
||||
self.0.index_mut(&key.entity())
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IndexMut<usize> for EntityIndexMap<V> {
|
||||
fn index_mut(&mut self, key: usize) -> &mut V {
|
||||
self.0.index_mut(key)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V> IntoIterator for &'a EntityIndexMap<V> {
|
||||
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<V> {
|
||||
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<V> IntoIterator for EntityIndexMap<V> {
|
||||
type Item = (Entity, V);
|
||||
type IntoIter = IntoIter<V>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
IntoIter(self.0.into_iter(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V1, V2, S2> PartialEq<IndexMap<Entity, V2, S2>> for EntityIndexMap<V1>
|
||||
where
|
||||
V1: PartialEq<V2>,
|
||||
S2: BuildHasher,
|
||||
{
|
||||
fn eq(&self, other: &IndexMap<Entity, V2, S2>) -> bool {
|
||||
self.0.eq(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V1, V2> PartialEq<EntityIndexMap<V2>> for EntityIndexMap<V1>
|
||||
where
|
||||
V1: PartialEq<V2>,
|
||||
{
|
||||
fn eq(&self, other: &EntityIndexMap<V2>) -> bool {
|
||||
self.0.eq(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Eq> Eq for EntityIndexMap<V> {}
|
||||
|
||||
/// 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<S>);
|
||||
|
||||
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::Item> {
|
||||
self.0.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> DoubleEndedIterator for Iter<'_, V> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
self.0.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> ExactSizeIterator for Iter<'_, V> {}
|
||||
|
||||
impl<V> FusedIterator for Iter<'_, V> {}
|
||||
|
||||
impl<V> Clone for Iter<'_, V> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Debug> Debug for Iter<'_, V> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Iter").field(&self.0).field(&self.1).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> 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<S>);
|
||||
|
||||
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::Item> {
|
||||
self.0.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> DoubleEndedIterator for IterMut<'_, V> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
self.0.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> ExactSizeIterator for IterMut<'_, V> {}
|
||||
|
||||
impl<V> FusedIterator for IterMut<'_, V> {}
|
||||
|
||||
impl<V: Debug> Debug for IterMut<'_, V> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("IterMut")
|
||||
.field(&self.0)
|
||||
.field(&self.1)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> 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<V, S = EntityHash>(map::IntoIter<Entity, V>, PhantomData<S>);
|
||||
|
||||
impl<V> IntoIter<V> {
|
||||
/// Returns the inner [`IntoIter`](map::IntoIter).
|
||||
pub fn into_inner(self) -> map::IntoIter<Entity, V> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Deref for IntoIter<V> {
|
||||
type Target = map::IntoIter<Entity, V>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Iterator for IntoIter<V> {
|
||||
type Item = (Entity, V);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.0.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> DoubleEndedIterator for IntoIter<V> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
self.0.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> ExactSizeIterator for IntoIter<V> {}
|
||||
|
||||
impl<V> FusedIterator for IntoIter<V> {}
|
||||
|
||||
impl<V: Clone> Clone for IntoIter<V> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Debug> Debug for IntoIter<V> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("IntoIter")
|
||||
.field(&self.0)
|
||||
.field(&self.1)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Default for IntoIter<V> {
|
||||
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<S>);
|
||||
|
||||
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<V> Iterator for Drain<'_, V> {
|
||||
type Item = (Entity, V);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.0.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> DoubleEndedIterator for Drain<'_, V> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
self.0.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> ExactSizeIterator for Drain<'_, V> {}
|
||||
|
||||
impl<V> FusedIterator for Drain<'_, V> {}
|
||||
|
||||
impl<V: Debug> 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<S>);
|
||||
|
||||
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::Item> {
|
||||
self.0.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> DoubleEndedIterator for Keys<'_, V> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
self.0.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> ExactSizeIterator for Keys<'_, V> {}
|
||||
|
||||
impl<V> FusedIterator for Keys<'_, V> {}
|
||||
|
||||
impl<V> Index<usize> for Keys<'_, V> {
|
||||
type Output = Entity;
|
||||
|
||||
fn index(&self, index: usize) -> &Entity {
|
||||
self.0.index(index)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Clone for Keys<'_, V> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Debug> Debug for Keys<'_, V> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Keys").field(&self.0).field(&self.1).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Default for Keys<'_, V> {
|
||||
fn default() -> Self {
|
||||
Self(Default::default(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: Keys stems from a correctly behaving `IndexMap<Entity, V, EntityHash>`.
|
||||
unsafe impl<V> 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<V, S = EntityHash>(map::IntoKeys<Entity, V>, PhantomData<S>);
|
||||
|
||||
impl<V> IntoKeys<V> {
|
||||
/// Returns the inner [`IntoKeys`](map::IntoKeys).
|
||||
pub fn into_inner(self) -> map::IntoKeys<Entity, V> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Deref for IntoKeys<V> {
|
||||
type Target = map::IntoKeys<Entity, V>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Iterator for IntoKeys<V> {
|
||||
type Item = Entity;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.0.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> DoubleEndedIterator for IntoKeys<V> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
self.0.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> ExactSizeIterator for IntoKeys<V> {}
|
||||
|
||||
impl<V> FusedIterator for IntoKeys<V> {}
|
||||
|
||||
impl<V: Debug> Debug for IntoKeys<V> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("IntoKeys")
|
||||
.field(&self.0)
|
||||
.field(&self.1)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Default for IntoKeys<V> {
|
||||
fn default() -> Self {
|
||||
Self(Default::default(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: IntoKeys stems from a correctly behaving `IndexMap<Entity, V, EntityHash>`.
|
||||
unsafe impl<V> EntitySetIterator for IntoKeys<V> {}
|
364
crates/bevy_ecs/src/entity/index_set.rs
Normal file
364
crates/bevy_ecs/src/entity/index_set.rs
Normal file
@ -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<Entity, EntityHash>);
|
||||
|
||||
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<Entity, EntityHash> {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Clears the `IndexSet` in the given index range, returning those values
|
||||
/// as a drain iterator.
|
||||
///
|
||||
/// Equivalent to [`IndexSet::drain`].
|
||||
pub fn drain<R: RangeBounds<usize>>(&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<Entity, EntityHash>;
|
||||
|
||||
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<T: IntoIterator<Item = &'a Entity>>(&mut self, iter: T) {
|
||||
self.0.extend(iter);
|
||||
}
|
||||
}
|
||||
|
||||
impl Extend<Entity> for EntityIndexSet {
|
||||
fn extend<T: IntoIterator<Item = Entity>>(&mut self, iter: T) {
|
||||
self.0.extend(iter);
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> From<[Entity; N]> for EntityIndexSet {
|
||||
fn from(value: [Entity; N]) -> Self {
|
||||
Self(IndexSet::from_iter(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl FromIterator<Entity> for EntityIndexSet {
|
||||
fn from_iter<I: IntoIterator<Item = Entity>>(iterable: I) -> Self {
|
||||
Self(IndexSet::from_iter(iterable))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S2> PartialEq<IndexSet<Entity, S2>> for EntityIndexSet
|
||||
where
|
||||
S2: BuildHasher,
|
||||
{
|
||||
fn eq(&self, other: &IndexSet<Entity, S2>) -> 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<usize> 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<S>);
|
||||
|
||||
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::Item> {
|
||||
self.0.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Iter<'_> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
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<Entity, EntityHash>`.
|
||||
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<S = EntityHash>(set::IntoIter<Entity>, PhantomData<S>);
|
||||
|
||||
impl IntoIter {
|
||||
/// Returns the inner [`IntoIter`](set::IntoIter).
|
||||
pub fn into_inner(self) -> set::IntoIter<Entity> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for IntoIter {
|
||||
type Target = set::IntoIter<Entity>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for IntoIter {
|
||||
type Item = Entity;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.0.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for IntoIter {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
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<Entity, EntityHash>`.
|
||||
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<S>);
|
||||
|
||||
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::Item> {
|
||||
self.0.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Drain<'_> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
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<Entity, EntityHash>`.
|
||||
unsafe impl EntitySetIterator for Drain<'_> {}
|
||||
|
||||
// SAFETY: Difference stems from two correctly behaving `IndexSet<Entity, EntityHash>`s.
|
||||
unsafe impl EntitySetIterator for set::Difference<'_, Entity, EntityHash> {}
|
||||
|
||||
// SAFETY: Intersection stems from two correctly behaving `IndexSet<Entity, EntityHash>`s.
|
||||
unsafe impl EntitySetIterator for set::Intersection<'_, Entity, EntityHash> {}
|
||||
|
||||
// SAFETY: SymmetricDifference stems from two correctly behaving `IndexSet<Entity, EntityHash>`s.
|
||||
unsafe impl EntitySetIterator for set::SymmetricDifference<'_, Entity, EntityHash, EntityHash> {}
|
||||
|
||||
// SAFETY: Union stems from two correctly behaving `IndexSet<Entity, EntityHash>`s.
|
||||
unsafe impl EntitySetIterator for set::Union<'_, Entity, EntityHash> {}
|
||||
|
||||
// SAFETY: Splice stems from a correctly behaving `IndexSet<Entity, EntityHash>`s.
|
||||
unsafe impl<I: Iterator<Item = Entity>> EntitySetIterator
|
||||
for set::Splice<'_, I, Entity, EntityHash>
|
||||
{
|
||||
}
|
@ -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::{
|
||||
|
Loading…
Reference in New Issue
Block a user