Path: blob/main/crates/bevy_ecs/src/entity/entity_set.rs
6849 views
use alloc::{1boxed::Box,2collections::{btree_map, btree_set},3rc::Rc,4};5use bevy_platform::collections::HashSet;67use core::{8array,9fmt::{Debug, Formatter},10hash::{BuildHasher, Hash},11iter::{self, FusedIterator},12option, result,13};1415use super::{Entity, UniqueEntityEquivalentSlice};1617use bevy_platform::sync::Arc;1819/// A trait for types that contain an [`Entity`].20///21/// This trait behaves similarly to `Borrow<Entity>`, but yielding `Entity` directly.22///23/// It should only be implemented when:24/// - Retrieving the [`Entity`] is a simple operation.25/// - The [`Entity`] contained by the type is unambiguous.26pub trait ContainsEntity {27/// Returns the contained entity.28fn entity(&self) -> Entity;29}3031/// A trait for types that represent an [`Entity`].32///33/// Comparison trait behavior between an [`EntityEquivalent`] type and its underlying entity will match.34/// This property includes [`PartialEq`], [`Eq`], [`PartialOrd`], [`Ord`] and [`Hash`],35/// and remains even after [`Clone`] and/or [`Borrow`] calls.36///37/// # Safety38/// Any [`PartialEq`], [`Eq`], [`PartialOrd`], and [`Ord`] impls must evaluate the same for `Self` and39/// its underlying entity.40/// `x.entity() == y.entity()` must be equivalent to `x == y`.41///42/// The above equivalence must also hold through and between calls to any [`Clone`] and43/// [`Borrow`]/[`BorrowMut`] impls in place of [`entity()`].44///45/// The result of [`entity()`] must be unaffected by any interior mutability.46///47/// The aforementioned properties imply determinism in both [`entity()`] calls48/// and comparison trait behavior.49///50/// All [`Hash`] impls except that for [`Entity`] must delegate to the [`Hash`] impl of51/// another [`EntityEquivalent`] type. All conversions to the delegatee within the [`Hash`] impl must52/// follow [`entity()`] equivalence.53///54/// It should be noted that [`Hash`] is *not* a comparison trait, and with [`Hash::hash`] being forcibly55/// generic over all [`Hasher`]s, **cannot** guarantee determinism or uniqueness of any final hash values56/// on its own.57/// To obtain hash values forming the same total order as [`Entity`], any [`Hasher`] used must be58/// deterministic and concerning [`Entity`], collisionless.59/// Standard library hash collections handle collisions with an [`Eq`] fallback, but do not account for60/// determinism when [`BuildHasher`] is unspecified,.61///62/// [`Hash`]: core::hash::Hash63/// [`Hasher`]: core::hash::Hasher64/// [`Borrow`]: core::borrow::Borrow65/// [`BorrowMut`]: core::borrow::BorrowMut66/// [`entity()`]: ContainsEntity::entity67pub unsafe trait EntityEquivalent: ContainsEntity + Eq {}6869impl ContainsEntity for Entity {70fn entity(&self) -> Entity {71*self72}73}7475// SAFETY:76// The trait implementations of Entity are correct and deterministic.77unsafe impl EntityEquivalent for Entity {}7879impl<T: ContainsEntity> ContainsEntity for &T {80fn entity(&self) -> Entity {81(**self).entity()82}83}8485// SAFETY:86// `&T` delegates `PartialEq`, `Eq`, `PartialOrd`, `Ord`, and `Hash` to T.87// `Clone` and `Borrow` maintain equality.88// `&T` is `Freeze`.89unsafe impl<T: EntityEquivalent> EntityEquivalent for &T {}9091impl<T: ContainsEntity> ContainsEntity for &mut T {92fn entity(&self) -> Entity {93(**self).entity()94}95}9697// SAFETY:98// `&mut T` delegates `PartialEq`, `Eq`, `PartialOrd`, `Ord`, and `Hash` to T.99// `Borrow` and `BorrowMut` maintain equality.100// `&mut T` is `Freeze`.101unsafe impl<T: EntityEquivalent> EntityEquivalent for &mut T {}102103impl<T: ContainsEntity> ContainsEntity for Box<T> {104fn entity(&self) -> Entity {105(**self).entity()106}107}108109// SAFETY:110// `Box<T>` delegates `PartialEq`, `Eq`, `PartialOrd`, `Ord`, and `Hash` to T.111// `Clone`, `Borrow` and `BorrowMut` maintain equality.112// `Box<T>` is `Freeze`.113unsafe impl<T: EntityEquivalent> EntityEquivalent for Box<T> {}114115impl<T: ContainsEntity> ContainsEntity for Rc<T> {116fn entity(&self) -> Entity {117(**self).entity()118}119}120121// SAFETY:122// `Rc<T>` delegates `PartialEq`, `Eq`, `PartialOrd`, `Ord`, and `Hash` to T.123// `Clone`, `Borrow` and `BorrowMut` maintain equality.124// `Rc<T>` is `Freeze`.125unsafe impl<T: EntityEquivalent> EntityEquivalent for Rc<T> {}126127impl<T: ContainsEntity> ContainsEntity for Arc<T> {128fn entity(&self) -> Entity {129(**self).entity()130}131}132133// SAFETY:134// `Arc<T>` delegates `PartialEq`, `Eq`, `PartialOrd`, `Ord`, and `Hash` to T.135// `Clone`, `Borrow` and `BorrowMut` maintain equality.136// `Arc<T>` is `Freeze`.137unsafe impl<T: EntityEquivalent> EntityEquivalent for Arc<T> {}138139/// A set of unique entities.140///141/// Any element returned by [`Self::IntoIter`] will compare non-equal to every other element in the iterator.142/// As a consequence, [`into_iter()`] on `EntitySet` will always produce another `EntitySet`.143///144/// Implementing this trait allows for unique query iteration over a list of entities.145/// See [`iter_many_unique`] and [`iter_many_unique_mut`]146///147/// Note that there is no guarantee of the [`IntoIterator`] impl being deterministic,148/// it might return different iterators when called multiple times.149/// Neither is there a guarantee that the comparison trait impls of `EntitySet` match that150/// of the respective [`EntitySetIterator`] (or of a [`Vec`] collected from its elements)151///152/// [`Self::IntoIter`]: IntoIterator::IntoIter153/// [`into_iter()`]: IntoIterator::into_iter154/// [`iter_many_unique`]: crate::system::Query::iter_many_unique155/// [`iter_many_unique_mut`]: crate::system::Query::iter_many_unique_mut156/// [`Vec`]: alloc::vec::Vec157pub trait EntitySet: IntoIterator<IntoIter: EntitySetIterator> {}158159impl<T: IntoIterator<IntoIter: EntitySetIterator>> EntitySet for T {}160161/// An iterator over a set of unique entities.162///163/// Every `EntitySetIterator` is also [`EntitySet`].164///165/// # Safety166///167/// `x != y` must hold for any 2 elements returned by the iterator.168/// This is always true for iterators that cannot return more than one element.169pub unsafe trait EntitySetIterator: Iterator<Item: EntityEquivalent> {170/// Transforms an `EntitySetIterator` into a collection.171///172/// This is a specialized form of [`collect`], for collections which benefit from the uniqueness guarantee.173/// When present, this should always be preferred over [`collect`].174///175/// [`collect`]: Iterator::collect176// FIXME: When subtrait item shadowing stabilizes, this should be renamed and shadow `Iterator::collect`177fn collect_set<B: FromEntitySetIterator<Self::Item>>(self) -> B178where179Self: Sized,180{181FromEntitySetIterator::from_entity_set_iter(self)182}183}184185// SAFETY:186// A correct `BTreeMap` contains only unique keys.187// EntityEquivalent guarantees a trustworthy Ord impl for T, and thus a correct `BTreeMap`.188unsafe impl<K: EntityEquivalent, V> EntitySetIterator for btree_map::Keys<'_, K, V> {}189190// SAFETY:191// A correct `BTreeMap` contains only unique keys.192// EntityEquivalent guarantees a trustworthy Ord impl for T, and thus a correct `BTreeMap`.193unsafe impl<K: EntityEquivalent, V> EntitySetIterator for btree_map::IntoKeys<K, V> {}194195// SAFETY:196// A correct `BTreeSet` contains only unique elements.197// EntityEquivalent guarantees a trustworthy Ord impl for T, and thus a correct `BTreeSet`.198// The sub-range maintains uniqueness.199unsafe impl<T: EntityEquivalent> EntitySetIterator for btree_set::Range<'_, T> {}200201// SAFETY:202// A correct `BTreeSet` contains only unique elements.203// EntityEquivalent guarantees a trustworthy Ord impl for T, and thus a correct `BTreeSet`.204// The "intersection" operation maintains uniqueness.205unsafe impl<T: EntityEquivalent + Ord> EntitySetIterator for btree_set::Intersection<'_, T> {}206207// SAFETY:208// A correct `BTreeSet` contains only unique elements.209// EntityEquivalent guarantees a trustworthy Ord impl for T, and thus a correct `BTreeSet`.210// The "union" operation maintains uniqueness.211unsafe impl<T: EntityEquivalent + Ord> EntitySetIterator for btree_set::Union<'_, T> {}212213// SAFETY:214// A correct `BTreeSet` contains only unique elements.215// EntityEquivalent guarantees a trustworthy Ord impl for T, and thus a correct `BTreeSet`.216// The "difference" operation maintains uniqueness.217unsafe impl<T: EntityEquivalent + Ord> EntitySetIterator for btree_set::Difference<'_, T> {}218219// SAFETY:220// A correct `BTreeSet` contains only unique elements.221// EntityEquivalent guarantees a trustworthy Ord impl for T, and thus a correct `BTreeSet`.222// The "symmetric difference" operation maintains uniqueness.223unsafe impl<T: EntityEquivalent + Ord> EntitySetIterator for btree_set::SymmetricDifference<'_, T> {}224225// SAFETY:226// A correct `BTreeSet` contains only unique elements.227// EntityEquivalent guarantees a trustworthy Ord impl for T, and thus a correct `BTreeSet`.228unsafe impl<T: EntityEquivalent> EntitySetIterator for btree_set::Iter<'_, T> {}229230// SAFETY:231// A correct `BTreeSet` contains only unique elements.232// EntityEquivalent guarantees a trustworthy Ord impl for T, and thus a correct `BTreeSet`.233unsafe impl<T: EntityEquivalent> EntitySetIterator for btree_set::IntoIter<T> {}234235// SAFETY: This iterator only returns one element.236unsafe impl<T: EntityEquivalent> EntitySetIterator for option::Iter<'_, T> {}237238// SAFETY: This iterator only returns one element.239// unsafe impl<T: EntityEquivalent> EntitySetIterator for option::IterMut<'_, T> {}240241// SAFETY: This iterator only returns one element.242unsafe impl<T: EntityEquivalent> EntitySetIterator for option::IntoIter<T> {}243244// SAFETY: This iterator only returns one element.245unsafe impl<T: EntityEquivalent> EntitySetIterator for result::Iter<'_, T> {}246247// SAFETY: This iterator only returns one element.248// unsafe impl<T: EntityEquivalent> EntitySetIterator for result::IterMut<'_, T> {}249250// SAFETY: This iterator only returns one element.251unsafe impl<T: EntityEquivalent> EntitySetIterator for result::IntoIter<T> {}252253// SAFETY: This iterator only returns one element.254unsafe impl<T: EntityEquivalent> EntitySetIterator for array::IntoIter<T, 1> {}255256// SAFETY: This iterator does not return any elements.257unsafe impl<T: EntityEquivalent> EntitySetIterator for array::IntoIter<T, 0> {}258259// SAFETY: This iterator only returns one element.260unsafe impl<T: EntityEquivalent, F: FnOnce() -> T> EntitySetIterator for iter::OnceWith<F> {}261262// SAFETY: This iterator only returns one element.263unsafe impl<T: EntityEquivalent> EntitySetIterator for iter::Once<T> {}264265// SAFETY: This iterator does not return any elements.266unsafe impl<T: EntityEquivalent> EntitySetIterator for iter::Empty<T> {}267268// SAFETY: Taking a mutable reference of an iterator has no effect on its elements.269unsafe impl<I: EntitySetIterator + ?Sized> EntitySetIterator for &mut I {}270271// SAFETY: Boxing an iterator has no effect on its elements.272unsafe impl<I: EntitySetIterator + ?Sized> EntitySetIterator for Box<I> {}273274// SAFETY: EntityEquivalent ensures that Copy does not affect equality, via its restrictions on Clone.275unsafe impl<'a, T: 'a + EntityEquivalent + Copy, I: EntitySetIterator<Item = &'a T>>276EntitySetIterator for iter::Copied<I>277{278}279280// SAFETY: EntityEquivalent ensures that Clone does not affect equality.281unsafe impl<'a, T: 'a + EntityEquivalent + Clone, I: EntitySetIterator<Item = &'a T>>282EntitySetIterator for iter::Cloned<I>283{284}285286// SAFETY: Discarding elements maintains uniqueness.287unsafe impl<I: EntitySetIterator, P: FnMut(&<I as Iterator>::Item) -> bool> EntitySetIterator288for iter::Filter<I, P>289{290}291292// SAFETY: Yielding only `None` after yielding it once can only remove elements, which maintains uniqueness.293unsafe impl<I: EntitySetIterator> EntitySetIterator for iter::Fuse<I> {}294295// SAFETY:296// Obtaining immutable references the elements of an iterator does not affect uniqueness.297// EntityEquivalent ensures the lack of interior mutability.298unsafe impl<I: EntitySetIterator, F: FnMut(&<I as Iterator>::Item)> EntitySetIterator299for iter::Inspect<I, F>300{301}302303// SAFETY: Reversing an iterator does not affect uniqueness.304unsafe impl<I: DoubleEndedIterator + EntitySetIterator> EntitySetIterator for iter::Rev<I> {}305306// SAFETY: Discarding elements maintains uniqueness.307unsafe impl<I: EntitySetIterator> EntitySetIterator for iter::Skip<I> {}308309// SAFETY: Discarding elements maintains uniqueness.310unsafe impl<I: EntitySetIterator, P: FnMut(&<I as Iterator>::Item) -> bool> EntitySetIterator311for iter::SkipWhile<I, P>312{313}314315// SAFETY: Discarding elements maintains uniqueness.316unsafe impl<I: EntitySetIterator> EntitySetIterator for iter::Take<I> {}317318// SAFETY: Discarding elements maintains uniqueness.319unsafe impl<I: EntitySetIterator, P: FnMut(&<I as Iterator>::Item) -> bool> EntitySetIterator320for iter::TakeWhile<I, P>321{322}323324// SAFETY: Discarding elements maintains uniqueness.325unsafe impl<I: EntitySetIterator> EntitySetIterator for iter::StepBy<I> {}326327/// Conversion from an `EntitySetIterator`.328///329/// Some collections, while they can be constructed from plain iterators,330/// benefit strongly from the additional uniqueness guarantee [`EntitySetIterator`] offers.331/// Mirroring [`Iterator::collect`]/[`FromIterator::from_iter`], [`EntitySetIterator::collect_set`] and332/// `FromEntitySetIterator::from_entity_set_iter` can be used for construction.333///334/// See also: [`EntitySet`].335// FIXME: When subtrait item shadowing stabilizes, this should be renamed and shadow `FromIterator::from_iter`336pub trait FromEntitySetIterator<A: EntityEquivalent>: FromIterator<A> {337/// Creates a value from an [`EntitySetIterator`].338fn from_entity_set_iter<T: EntitySet<Item = A>>(set_iter: T) -> Self;339}340341impl<T: EntityEquivalent + Hash, S: BuildHasher + Default> FromEntitySetIterator<T>342for HashSet<T, S>343{344fn from_entity_set_iter<I: EntitySet<Item = T>>(set_iter: I) -> Self {345let iter = set_iter.into_iter();346let set = HashSet::<T, S>::with_capacity_and_hasher(iter.size_hint().0, S::default());347iter.fold(set, |mut set, e| {348// SAFETY: Every element in self is unique.349unsafe {350set.insert_unique_unchecked(e);351}352set353})354}355}356357/// An iterator that yields unique entities.358///359/// This wrapper can provide an [`EntitySetIterator`] implementation when an instance of `I` is known to uphold uniqueness.360pub struct UniqueEntityIter<I: Iterator<Item: EntityEquivalent>> {361iter: I,362}363364impl<I: EntitySetIterator> UniqueEntityIter<I> {365/// Constructs a `UniqueEntityIter` from an [`EntitySetIterator`].366pub fn from_entity_set_iterator<S>(iter: I) -> Self {367Self { iter }368}369}370371impl<I: Iterator<Item: EntityEquivalent>> UniqueEntityIter<I> {372/// Constructs a [`UniqueEntityIter`] from an iterator unsafely.373///374/// # Safety375/// `iter` must only yield unique elements.376/// As in, the resulting iterator must adhere to the safety contract of [`EntitySetIterator`].377pub unsafe fn from_iterator_unchecked(iter: I) -> Self {378Self { iter }379}380381/// Returns the inner `I`.382pub fn into_inner(self) -> I {383self.iter384}385386/// Returns a reference to the inner `I`.387pub fn as_inner(&self) -> &I {388&self.iter389}390391/// Returns a mutable reference to the inner `I`.392///393/// # Safety394///395/// `self` must always contain an iterator that yields unique elements,396/// even while this reference is live.397pub unsafe fn as_mut_inner(&mut self) -> &mut I {398&mut self.iter399}400}401402impl<I: Iterator<Item: EntityEquivalent>> Iterator for UniqueEntityIter<I> {403type Item = I::Item;404405fn next(&mut self) -> Option<Self::Item> {406self.iter.next()407}408409fn size_hint(&self) -> (usize, Option<usize>) {410self.iter.size_hint()411}412}413414impl<I: ExactSizeIterator<Item: EntityEquivalent>> ExactSizeIterator for UniqueEntityIter<I> {}415416impl<I: DoubleEndedIterator<Item: EntityEquivalent>> DoubleEndedIterator for UniqueEntityIter<I> {417fn next_back(&mut self) -> Option<Self::Item> {418self.iter.next_back()419}420}421422impl<I: FusedIterator<Item: EntityEquivalent>> FusedIterator for UniqueEntityIter<I> {}423424// SAFETY: The underlying iterator is ensured to only return unique elements by its construction.425unsafe impl<I: Iterator<Item: EntityEquivalent>> EntitySetIterator for UniqueEntityIter<I> {}426427impl<T, I: Iterator<Item: EntityEquivalent> + AsRef<[T]>> AsRef<[T]> for UniqueEntityIter<I> {428fn as_ref(&self) -> &[T] {429self.iter.as_ref()430}431}432433impl<T: EntityEquivalent, I: Iterator<Item: EntityEquivalent> + AsRef<[T]>>434AsRef<UniqueEntityEquivalentSlice<T>> for UniqueEntityIter<I>435{436fn as_ref(&self) -> &UniqueEntityEquivalentSlice<T> {437// SAFETY: All elements in the original slice are unique.438unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(self.iter.as_ref()) }439}440}441442impl<T: EntityEquivalent, I: Iterator<Item: EntityEquivalent> + AsMut<[T]>>443AsMut<UniqueEntityEquivalentSlice<T>> for UniqueEntityIter<I>444{445fn as_mut(&mut self) -> &mut UniqueEntityEquivalentSlice<T> {446// SAFETY: All elements in the original slice are unique.447unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked_mut(self.iter.as_mut()) }448}449}450451// Default does not guarantee uniqueness, meaning `I` needs to be EntitySetIterator.452impl<I: EntitySetIterator + Default> Default for UniqueEntityIter<I> {453fn default() -> Self {454Self {455iter: Default::default(),456}457}458}459460// Clone does not guarantee to maintain uniqueness, meaning `I` needs to be EntitySetIterator.461impl<I: EntitySetIterator + Clone> Clone for UniqueEntityIter<I> {462fn clone(&self) -> Self {463Self {464iter: self.iter.clone(),465}466}467}468469impl<I: Iterator<Item: EntityEquivalent> + Debug> Debug for UniqueEntityIter<I> {470fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {471f.debug_struct("UniqueEntityIter")472.field("iter", &self.iter)473.finish()474}475}476477#[cfg(test)]478mod tests {479use alloc::{vec, vec::Vec};480481use crate::prelude::{Schedule, World};482483use crate::component::Component;484use crate::entity::Entity;485use crate::query::{QueryState, With};486use crate::system::Query;487use crate::world::Mut;488489use super::UniqueEntityIter;490491#[derive(Component, Clone)]492pub struct Thing;493494#[expect(495clippy::iter_skip_zero,496reason = "The `skip(0)` is used to ensure that the `Skip` iterator implements `EntitySet`, which is needed to pass the iterator as the `entities` parameter."497)]498#[test]499fn preserving_uniqueness() {500let mut world = World::new();501502let mut query = QueryState::<&mut Thing>::new(&mut world);503504let spawn_batch: Vec<Entity> = world.spawn_batch(vec![Thing; 1000]).collect();505506// SAFETY: SpawnBatchIter is `EntitySetIterator`,507let mut unique_entity_iter =508unsafe { UniqueEntityIter::from_iterator_unchecked(spawn_batch.iter()) };509510let entity_set = unique_entity_iter511.by_ref()512.filter(|_| true)513.fuse()514.inspect(|_| ())515.rev()516.skip(0)517.skip_while(|_| false)518.take(1000)519.take_while(|_| true)520.step_by(2)521.cloned();522523// With `iter_many_mut` collecting is not possible, because you need to drop each `Mut`/`&mut` before the next is retrieved.524let _results: Vec<Mut<Thing>> =525query.iter_many_unique_mut(&mut world, entity_set).collect();526}527528#[test]529fn nesting_queries() {530let mut world = World::new();531532world.spawn_batch(vec![Thing; 1000]);533534pub fn system(535mut thing_entities: Query<Entity, With<Thing>>,536mut things: Query<&mut Thing>,537) {538things.iter_many_unique(thing_entities.iter());539things.iter_many_unique_mut(thing_entities.iter_mut());540}541542let mut schedule = Schedule::default();543schedule.add_systems(system);544schedule.run(&mut world);545}546}547548549