-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
General entity set cleanup #21498
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
General entity set cleanup #21498
Changes from 8 commits
513da58
4e08725
bb95355
dceec17
68546a9
1f1d205
a1530b0
3c0c67a
ac73915
f390dd3
a77aaaa
4c5ccaa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,7 +10,7 @@ use core::{ | |
| fmt::{Debug, Formatter}, | ||
| hash::{BuildHasher, Hash}, | ||
| iter::{self, FusedIterator}, | ||
| option, result, | ||
| option, ptr, result, | ||
| }; | ||
|
|
||
| use super::{Entity, UniqueEntityEquivalentSlice}; | ||
|
|
@@ -58,7 +58,7 @@ pub trait ContainsEntity { | |
| /// To obtain hash values forming the same total order as [`Entity`], any [`Hasher`] used must be | ||
| /// deterministic and concerning [`Entity`], collisionless. | ||
| /// Standard library hash collections handle collisions with an [`Eq`] fallback, but do not account for | ||
| /// determinism when [`BuildHasher`] is unspecified,. | ||
| /// determinism when [`BuildHasher`] is unspecified. | ||
| /// | ||
| /// [`Hash`]: core::hash::Hash | ||
| /// [`Hasher`]: core::hash::Hasher | ||
|
|
@@ -68,6 +68,7 @@ pub trait ContainsEntity { | |
| pub unsafe trait EntityEquivalent: ContainsEntity + Eq {} | ||
|
|
||
| impl ContainsEntity for Entity { | ||
| #[inline] | ||
| fn entity(&self) -> Entity { | ||
| *self | ||
| } | ||
|
|
@@ -78,6 +79,7 @@ impl ContainsEntity for Entity { | |
| unsafe impl EntityEquivalent for Entity {} | ||
|
|
||
| impl<T: ContainsEntity> ContainsEntity for &T { | ||
| #[inline] | ||
| fn entity(&self) -> Entity { | ||
| (**self).entity() | ||
| } | ||
|
|
@@ -90,6 +92,7 @@ impl<T: ContainsEntity> ContainsEntity for &T { | |
| unsafe impl<T: EntityEquivalent> EntityEquivalent for &T {} | ||
|
|
||
| impl<T: ContainsEntity> ContainsEntity for &mut T { | ||
| #[inline] | ||
| fn entity(&self) -> Entity { | ||
| (**self).entity() | ||
| } | ||
|
|
@@ -102,6 +105,7 @@ impl<T: ContainsEntity> ContainsEntity for &mut T { | |
| unsafe impl<T: EntityEquivalent> EntityEquivalent for &mut T {} | ||
|
|
||
| impl<T: ContainsEntity> ContainsEntity for Box<T> { | ||
| #[inline] | ||
| fn entity(&self) -> Entity { | ||
| (**self).entity() | ||
| } | ||
|
|
@@ -114,6 +118,7 @@ impl<T: ContainsEntity> ContainsEntity for Box<T> { | |
| unsafe impl<T: EntityEquivalent> EntityEquivalent for Box<T> {} | ||
|
|
||
| impl<T: ContainsEntity> ContainsEntity for Rc<T> { | ||
| #[inline] | ||
| fn entity(&self) -> Entity { | ||
| (**self).entity() | ||
| } | ||
|
|
@@ -126,6 +131,7 @@ impl<T: ContainsEntity> ContainsEntity for Rc<T> { | |
| unsafe impl<T: EntityEquivalent> EntityEquivalent for Rc<T> {} | ||
|
|
||
| impl<T: ContainsEntity> ContainsEntity for Arc<T> { | ||
| #[inline] | ||
| fn entity(&self) -> Entity { | ||
| (**self).entity() | ||
| } | ||
|
|
@@ -143,12 +149,12 @@ unsafe impl<T: EntityEquivalent> EntityEquivalent for Arc<T> {} | |
| /// As a consequence, [`into_iter()`] on `EntitySet` will always produce another `EntitySet`. | ||
| /// | ||
| /// Implementing this trait allows for unique query iteration over a list of entities. | ||
| /// See [`iter_many_unique`] and [`iter_many_unique_mut`] | ||
| /// See [`iter_many_unique`] and [`iter_many_unique_mut`]. | ||
| /// | ||
| /// Note that there is no guarantee of the [`IntoIterator`] impl being deterministic, | ||
| /// it might return different iterators when called multiple times. | ||
| /// Neither is there a guarantee that the comparison trait impls of `EntitySet` match that | ||
| /// of the respective [`EntitySetIterator`] (or of a [`Vec`] collected from its elements) | ||
| /// of the respective [`EntitySetIterator`] (or of a [`Vec`] collected from its elements). | ||
| /// | ||
| /// [`Self::IntoIter`]: IntoIterator::IntoIter | ||
| /// [`into_iter()`]: IntoIterator::into_iter | ||
|
|
@@ -342,6 +348,7 @@ pub trait FromEntitySetIterator<A: EntityEquivalent>: FromIterator<A> { | |
| impl<T: EntityEquivalent + Hash, S: BuildHasher + Default> FromEntitySetIterator<T> | ||
| for HashSet<T, S> | ||
| { | ||
| #[inline] | ||
| fn from_entity_set_iter<I: EntitySet<Item = T>>(set_iter: I) -> Self { | ||
| let iter = set_iter.into_iter(); | ||
| let set = HashSet::<T, S>::with_capacity_and_hasher(iter.size_hint().0, S::default()); | ||
|
|
@@ -358,14 +365,17 @@ impl<T: EntityEquivalent + Hash, S: BuildHasher + Default> FromEntitySetIterator | |
| /// An iterator that yields unique entities. | ||
| /// | ||
| /// This wrapper can provide an [`EntitySetIterator`] implementation when an instance of `I` is known to uphold uniqueness. | ||
| #[repr(transparent)] | ||
| pub struct UniqueEntityIter<I: Iterator<Item: EntityEquivalent>> { | ||
| iter: I, | ||
| } | ||
|
|
||
| impl<I: EntitySetIterator> UniqueEntityIter<I> { | ||
| /// Constructs a `UniqueEntityIter` from an [`EntitySetIterator`]. | ||
| pub fn from_entity_set_iterator<S>(iter: I) -> Self { | ||
| Self { iter } | ||
| #[inline] | ||
| pub const fn from_entity_set_iter(iter: I) -> Self { | ||
| // SAFETY: iter implements `EntitySetIterator`. | ||
| unsafe { Self::from_iter_unchecked(iter) } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -375,17 +385,42 @@ impl<I: Iterator<Item: EntityEquivalent>> UniqueEntityIter<I> { | |
| /// # Safety | ||
| /// `iter` must only yield unique elements. | ||
| /// As in, the resulting iterator must adhere to the safety contract of [`EntitySetIterator`]. | ||
| pub unsafe fn from_iterator_unchecked(iter: I) -> Self { | ||
| #[inline] | ||
| pub const unsafe fn from_iter_unchecked(iter: I) -> Self { | ||
| Self { iter } | ||
| } | ||
|
|
||
| /// Constructs a [`UniqueEntityIter`] from an iterator unsafely. | ||
| /// | ||
| /// # Safety | ||
| /// `iter` must only yield unique elements. | ||
| /// As in, the resulting iterator must adhere to the safety contract of [`EntitySetIterator`]. | ||
| #[inline] | ||
| pub const unsafe fn from_iter_ref_unchecked(iter: &I) -> &Self { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess this makes sense for completeness, but there's not much you can do with an Same thing for
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For iterators, remember that is a For Right now, mutable |
||
| // SAFETY: UniqueEntityIter is a transparent wrapper around I. | ||
| unsafe { &*ptr::from_ref(iter).cast() } | ||
| } | ||
|
|
||
| /// Constructs a [`UniqueEntityIter`] from an iterator unsafely. | ||
| /// | ||
| /// # Safety | ||
| /// `iter` must only yield unique elements. | ||
| /// As in, the resulting iterator must adhere to the safety contract of [`EntitySetIterator`]. | ||
| #[inline] | ||
| pub const unsafe fn from_iter_mut_unchecked(iter: &mut I) -> &mut Self { | ||
| // SAFETY: UniqueEntityIter is a transparent wrapper around I. | ||
| unsafe { &mut *ptr::from_mut(iter).cast() } | ||
| } | ||
|
|
||
| /// Returns the inner `I`. | ||
| #[inline] | ||
| pub fn into_inner(self) -> I { | ||
| self.iter | ||
| } | ||
|
|
||
| /// Returns a reference to the inner `I`. | ||
| pub fn as_inner(&self) -> &I { | ||
| #[inline] | ||
| pub const fn as_inner(&self) -> &I { | ||
| &self.iter | ||
| } | ||
|
|
||
|
|
@@ -395,18 +430,21 @@ impl<I: Iterator<Item: EntityEquivalent>> UniqueEntityIter<I> { | |
| /// | ||
| /// `self` must always contain an iterator that yields unique elements, | ||
| /// even while this reference is live. | ||
| pub unsafe fn as_mut_inner(&mut self) -> &mut I { | ||
| #[inline] | ||
| pub const unsafe fn as_mut_inner(&mut self) -> &mut I { | ||
| &mut self.iter | ||
| } | ||
| } | ||
|
|
||
| impl<I: Iterator<Item: EntityEquivalent>> Iterator for UniqueEntityIter<I> { | ||
| type Item = I::Item; | ||
|
|
||
| #[inline] | ||
|
Victoronz marked this conversation as resolved.
Outdated
|
||
| fn next(&mut self) -> Option<Self::Item> { | ||
| self.iter.next() | ||
| } | ||
|
|
||
| #[inline] | ||
| fn size_hint(&self) -> (usize, Option<usize>) { | ||
| self.iter.size_hint() | ||
| } | ||
|
|
@@ -415,6 +453,7 @@ impl<I: Iterator<Item: EntityEquivalent>> Iterator for UniqueEntityIter<I> { | |
| impl<I: ExactSizeIterator<Item: EntityEquivalent>> ExactSizeIterator for UniqueEntityIter<I> {} | ||
|
|
||
| impl<I: DoubleEndedIterator<Item: EntityEquivalent>> DoubleEndedIterator for UniqueEntityIter<I> { | ||
| #[inline] | ||
| fn next_back(&mut self) -> Option<Self::Item> { | ||
| self.iter.next_back() | ||
| } | ||
|
|
@@ -426,6 +465,7 @@ impl<I: FusedIterator<Item: EntityEquivalent>> FusedIterator for UniqueEntityIte | |
| unsafe impl<I: Iterator<Item: EntityEquivalent>> EntitySetIterator for UniqueEntityIter<I> {} | ||
|
|
||
| impl<T, I: Iterator<Item: EntityEquivalent> + AsRef<[T]>> AsRef<[T]> for UniqueEntityIter<I> { | ||
| #[inline] | ||
| fn as_ref(&self) -> &[T] { | ||
| self.iter.as_ref() | ||
| } | ||
|
|
@@ -434,6 +474,7 @@ impl<T, I: Iterator<Item: EntityEquivalent> + AsRef<[T]>> AsRef<[T]> for UniqueE | |
| impl<T: EntityEquivalent, I: Iterator<Item: EntityEquivalent> + AsRef<[T]>> | ||
| AsRef<UniqueEntityEquivalentSlice<T>> for UniqueEntityIter<I> | ||
| { | ||
| #[inline] | ||
| fn as_ref(&self) -> &UniqueEntityEquivalentSlice<T> { | ||
| // SAFETY: All elements in the original slice are unique. | ||
| unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(self.iter.as_ref()) } | ||
|
|
@@ -443,6 +484,7 @@ impl<T: EntityEquivalent, I: Iterator<Item: EntityEquivalent> + AsRef<[T]>> | |
| impl<T: EntityEquivalent, I: Iterator<Item: EntityEquivalent> + AsMut<[T]>> | ||
| AsMut<UniqueEntityEquivalentSlice<T>> for UniqueEntityIter<I> | ||
| { | ||
| #[inline] | ||
| fn as_mut(&mut self) -> &mut UniqueEntityEquivalentSlice<T> { | ||
| // SAFETY: All elements in the original slice are unique. | ||
| unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked_mut(self.iter.as_mut()) } | ||
|
|
@@ -451,6 +493,7 @@ impl<T: EntityEquivalent, I: Iterator<Item: EntityEquivalent> + AsMut<[T]>> | |
|
|
||
| // Default does not guarantee uniqueness, meaning `I` needs to be EntitySetIterator. | ||
| impl<I: EntitySetIterator + Default> Default for UniqueEntityIter<I> { | ||
| #[inline] | ||
| fn default() -> Self { | ||
| Self { | ||
| iter: Default::default(), | ||
|
|
@@ -460,6 +503,7 @@ impl<I: EntitySetIterator + Default> Default for UniqueEntityIter<I> { | |
|
|
||
| // Clone does not guarantee to maintain uniqueness, meaning `I` needs to be EntitySetIterator. | ||
| impl<I: EntitySetIterator + Clone> Clone for UniqueEntityIter<I> { | ||
| #[inline] | ||
| fn clone(&self) -> Self { | ||
| Self { | ||
| iter: self.iter.clone(), | ||
|
|
@@ -506,7 +550,7 @@ mod tests { | |
|
|
||
| // SAFETY: SpawnBatchIter is `EntitySetIterator`, | ||
| let mut unique_entity_iter = | ||
| unsafe { UniqueEntityIter::from_iterator_unchecked(spawn_batch.iter()) }; | ||
| unsafe { UniqueEntityIter::from_iter_unchecked(spawn_batch.iter()) }; | ||
|
|
||
| let entity_set = unique_entity_iter | ||
| .by_ref() | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.