diff --git a/crates/bevy_ecs/clippy.toml b/crates/bevy_ecs/clippy.toml new file mode 100644 index 0000000000000..6532f723e5e2e --- /dev/null +++ b/crates/bevy_ecs/clippy.toml @@ -0,0 +1,4 @@ +disallowed-methods = [ + { path = "UniqueEntityVec::from_iter", reason = "Use UniqueEntityVec::from_entity_set_iter if possible, it skips validation" }, + { path = "EntitySetIterator::collect::", reason = "Use EntitySetIterator::collect_set if possible, it skips validation" }, +] diff --git a/crates/bevy_ecs/src/entity/mod.rs b/crates/bevy_ecs/src/entity/mod.rs index 3fa63d37fa777..8be4df3643149 100644 --- a/crates/bevy_ecs/src/entity/mod.rs +++ b/crates/bevy_ecs/src/entity/mod.rs @@ -50,6 +50,10 @@ pub use entity_set::*; pub use map_entities::*; pub use visit_entities::*; +mod unique_vec; + +pub use unique_vec::*; + mod hash; pub use hash::*; diff --git a/crates/bevy_ecs/src/entity/unique_vec.rs b/crates/bevy_ecs/src/entity/unique_vec.rs new file mode 100644 index 0000000000000..32b4f0b03751f --- /dev/null +++ b/crates/bevy_ecs/src/entity/unique_vec.rs @@ -0,0 +1,735 @@ +use core::{ + borrow::Borrow, + mem::MaybeUninit, + ops::{Index, RangeBounds}, + slice, +}; + +use alloc::{ + borrow::Cow, + boxed::Box, + collections::{BTreeSet, BinaryHeap, TryReserveError, VecDeque}, + rc::Rc, + sync::Arc, + vec::{self, Vec}, +}; + +use super::{EntitySet, FromEntitySetIterator, TrustedEntityBorrow, UniqueEntityIter}; + +/// A `Vec` that contains only unique entities. +/// +/// "Unique" means that `x != y` holds for any 2 entities in this collection. +/// This is always true when less than 2 entities are present. +/// +/// This type is best obtained by its `FromEntitySetIterator` impl, via either +/// `EntityIterator::collect_set` or `UniqueEntityVec::from_entity_iter`. +/// +/// While this type can be constructed via `Iterator::collect`, doing so is inefficient, +/// and not recommended. +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct UniqueEntityVec(Vec); + +impl UniqueEntityVec { + /// Constructs a new, empty `UniqueEntityVec`. + /// + /// Equivalent to [`Vec::new`]. + pub const fn new() -> Self { + Self(Vec::new()) + } + + /// Constructs a new, empty `UniqueEntityVec` with at least the specified capacity. + /// + /// Equivalent to [`Vec::with_capacity`] + pub fn with_capacity(capacity: usize) -> Self { + Self(Vec::with_capacity(capacity)) + } + + /// Creates a `UniqueEntityVec` directly from a pointer, a length, and a capacity. + /// + /// Equivalent to [`Vec::from_raw_parts`]. + /// + /// # Safety + /// + /// It must be safe to call [`Vec::from_raw_parts`] with these inputs, + /// and the resulting [`Vec`] must only contain unique elements. + pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self { + // SAFETY: Caller ensures it's safe to call `Vec::from_raw_parts` + Self(unsafe { Vec::from_raw_parts(ptr, length, capacity) }) + } + + /// Constructs a `UniqueEntityVec` from a [`Vec`] unsafely. + /// + /// # Safety + /// + /// `vec` must contain only unique elements. + pub unsafe fn from_vec_unchecked(vec: Vec) -> Self { + Self(vec) + } + + /// Returns the inner [`Vec`]. + pub fn into_inner(self) -> Vec { + self.0 + } + + /// Returns a reference to the inner [`Vec`]. + pub fn as_vec(&self) -> &Vec { + &self.0 + } + + /// Returns a mutable reference to the inner [`Vec`]. + /// + /// # Safety + /// + /// The elements of this `Vec` must always remain unique, even while + /// this mutable reference is live. + pub unsafe fn as_mut_vec(&mut self) -> &mut Vec { + &mut self.0 + } + + /// Returns the total number of elements the vector can hold without + /// reallocating. + /// + /// Equivalent to [`Vec::capacity`]. + pub fn capacity(&self) -> usize { + self.0.capacity() + } + + /// Reserves capacity for at least `additional` more elements to be inserted + /// in the given `Vec`. + /// + /// Equivalent to [`Vec::reserve`]. + pub fn reserve(&mut self, additional: usize) { + self.0.reserve(additional); + } + + /// Reserves the minimum capacity for at least `additional` more elements to + /// be inserted in the given `UniqueEntityVec`. + /// + /// Equivalent to [`Vec::reserve_exact`]. + pub fn reserve_exact(&mut self, additional: usize) { + self.0.reserve_exact(additional); + } + + /// Tries to reserve capacity for at least `additional` more elements to be inserted + /// in the given `Vec`. + /// + /// Equivalent to [`Vec::try_reserve`]. + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.0.try_reserve(additional) + } + + /// Tries to reserve the minimum capacity for at least `additional` + /// elements to be inserted in the given `Vec`. + /// + /// Equivalent to [`Vec::try_reserve_exact`]. + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.0.try_reserve_exact(additional) + } + + /// Shrinks the capacity of the vector as much as possible. + /// + /// Equivalent to [`Vec::shrink_to_fit`]. + pub fn shrink_to_fit(&mut self) { + self.0.shrink_to_fit(); + } + + /// Shrinks the capacity of the vector with a lower bound. + /// + /// Equivalent to [`Vec::shrink_to`]. + pub fn shrink_to(&mut self, min_capacity: usize) { + self.0.shrink_to(min_capacity); + } + + /// Shortens the vector, keeping the first `len` elements and dropping + /// the rest. + /// + /// Equivalent to [`Vec::truncate`]. + pub fn truncate(&mut self, len: usize) { + self.0.truncate(len); + } + + /// Returns a raw pointer to the vector's buffer, or a dangling raw pointer + /// valid for zero sized reads if the vector didn't allocate. + /// + /// Equivalent to [`Vec::as_ptr`]. + pub fn as_ptr(&self) -> *const T { + self.0.as_ptr() + } + /// Returns a raw mutable pointer to the vector's buffer, or a dangling + /// raw pointer valid for zero sized reads if the vector didn't allocate. + /// + /// Equivalent to [`Vec::as_mut_ptr`]. + pub fn as_mut_ptr(&mut self) -> *mut T { + self.0.as_mut_ptr() + } + + /// Forces the length of the vector to `new_len`. + /// + /// Equivalent to [`Vec::set_len`]. + /// + /// # Safety + /// + /// It must be safe to call [`Vec::set_len`] with these inputs, + /// and the resulting [`Vec`] must only contain unique elements. + pub unsafe fn set_len(&mut self, new_len: usize) { + // SAFETY: Caller ensures it's safe to call `Vec::set_len` + unsafe { self.0.set_len(new_len) }; + } + + /// Removes an element from the vector and returns it. + /// + /// Equivalent to [`Vec::swap_remove`]. + pub fn swap_remove(&mut self, index: usize) -> T { + self.0.swap_remove(index) + } + + /// Inserts an element at position `index` within the vector, shifting all + /// elements after it to the right. + /// + /// Equivalent to [`Vec::insert`]. + /// + /// # Safety + /// + /// No `T` contained by `self` may equal `element`. + pub unsafe fn insert(&mut self, index: usize, element: T) { + self.0.insert(index, element); + } + + /// Removes and returns the element at position `index` within the vector, + /// shifting all elements after it to the left. + /// + /// Equivalent to [`Vec::remove`]. + pub fn remove(&mut self, index: usize) -> T { + self.0.remove(index) + } + + /// Retains only the elements specified by the predicate. + /// + /// Equivalent to [`Vec::retain`]. + pub fn retain(&mut self, f: F) + where + F: FnMut(&T) -> bool, + { + self.0.retain(f); + } + + /// Retains only the elements specified by the predicate, passing a mutable reference to it. + /// + /// Equivalent to [`Vec::retain_mut`]. + /// + /// # Safety + /// + /// `self` must only contain unique elements after each individual execution of `f`. + pub unsafe fn retain_mut(&mut self, f: F) + where + F: FnMut(&mut T) -> bool, + { + self.0.retain_mut(f); + } + + /// Removes all but the first of consecutive elements in the vector that resolve to the same + /// key. + /// + /// Equivalent to [`Vec::dedup_by_key`]. + /// + /// # Safety + /// + /// `self` must only contain unique elements after each individual execution of `key`. + pub unsafe fn dedup_by_key(&mut self, key: F) + where + F: FnMut(&mut T) -> K, + K: PartialEq, + { + self.0.dedup_by_key(key); + } + + /// Removes all but the first of consecutive elements in the vector satisfying a given equality + /// relation. + /// + /// Equivalent to [`Vec::dedup_by`]. + /// + /// # Safety + /// + /// `self` must only contain unique elements after each individual execution of `same_bucket`. + pub unsafe fn dedup_by(&mut self, same_bucket: F) + where + F: FnMut(&mut T, &mut T) -> bool, + { + self.0.dedup_by(same_bucket); + } + + /// Appends an element to the back of a collection. + /// + /// Equivalent to [`Vec::push`]. + /// + /// # Safety + /// + /// No `T` contained by `self` may equal `element`. + pub unsafe fn push(&mut self, value: T) { + self.0.push(value); + } + + /// Moves all the elements of `other` into `self`, leaving `other` empty. + /// + /// Equivalent to [`Vec::append`]. + /// + /// # Safety + /// + /// `other` must contain no elements that equal any element in `self`. + pub unsafe fn append(&mut self, other: &mut UniqueEntityVec) { + self.0.append(&mut other.0); + } + + /// Removes the last element from a vector and returns it, or [`None`] if it + /// is empty. + /// + /// Equivalent to [`Vec::pop`]. + pub fn pop(&mut self) -> Option { + self.0.pop() + } + + /// Removes the specified range from the vector in bulk, returning all + /// removed elements as an iterator. + /// + /// Equivalent to [`Vec::drain`]. + pub fn drain(&mut self, range: R) -> Drain<'_, T> + where + R: RangeBounds, + { + // SAFETY: `self` and thus `range` contains only unique elements. + unsafe { UniqueEntityIter::from_iterator_unchecked(self.0.drain(range)) } + } + + /// Clears the vector, removing all values. + /// + /// Equivalent to [`Vec::clear`]. + pub fn clear(&mut self) { + self.0.clear(); + } + + /// Returns the number of elements in the vector, also referred to + /// as its 'length'. + /// + /// Equivalent to [`Vec::len`]. + pub fn len(&self) -> usize { + self.0.len() + } + + /// Returns `true` if the vector contains no elements. + /// + /// Equivalent to [`Vec::is_empty`]. + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + /// Splits the collection into two at the given index. + /// + /// Equivalent to [`Vec::split_off`]. + pub fn split_off(&mut self, at: usize) -> Self { + Self(self.0.split_off(at)) + } + + /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. + /// + /// Equivalent to [`Vec::resize_with`]. + /// + /// # Safety + /// + /// `f` must only produce unique `T`, and none of these may equal any `T` in `self`. + pub unsafe fn resize_with(&mut self, new_len: usize, f: F) + where + F: FnMut() -> T, + { + self.0.resize_with(new_len, f); + } + + /// Returns the remaining spare capacity of the vector as a slice of + /// [`MaybeUninit`]. + /// + /// Equivalent to [`Vec::spare_capacity_mut`]. + pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit] { + self.0.spare_capacity_mut() + } + + /// Creates a splicing iterator that replaces the specified range in the vector + /// with the given `replace_with` iterator and yields the removed items. + /// + /// Equivalent to [`Vec::splice`]. + /// + /// # Safety + /// + /// `replace_with` must not yield any elements that equal any elements in `self`, + /// except for those in `range`. + pub unsafe fn splice( + &mut self, + range: R, + replace_with: I, + ) -> Splice<'_, ::IntoIter> + where + R: RangeBounds, + I: EntitySet, + { + // SAFETY: `self` and thus `range` contains only unique elements. + UniqueEntityIter::from_iterator_unchecked(self.0.splice(range, replace_with)) + } +} + +impl Default for UniqueEntityVec { + fn default() -> Self { + Self(Vec::default()) + } +} + +impl<'a, T: TrustedEntityBorrow> IntoIterator for &'a UniqueEntityVec +where + &'a T: TrustedEntityBorrow, +{ + type Item = &'a T; + + type IntoIter = UniqueEntityIter>; + + fn into_iter(self) -> Self::IntoIter { + // SAFETY: `self` contains only unique elements. + unsafe { UniqueEntityIter::from_iterator_unchecked(self.0.iter()) } + } +} + +impl IntoIterator for UniqueEntityVec { + type Item = T; + + type IntoIter = IntoIter; + + fn into_iter(self) -> Self::IntoIter { + // SAFETY: `self` contains only unique elements. + unsafe { UniqueEntityIter::from_iterator_unchecked(self.0.into_iter()) } + } +} + +impl AsMut for UniqueEntityVec { + fn as_mut(&mut self) -> &mut UniqueEntityVec { + self + } +} + +impl AsRef for UniqueEntityVec { + fn as_ref(&self) -> &Self { + self + } +} + +impl AsRef> for UniqueEntityVec { + fn as_ref(&self) -> &Vec { + &self.0 + } +} + +impl Borrow> for UniqueEntityVec { + fn borrow(&self) -> &Vec { + &self.0 + } +} + +impl AsRef<[T]> for UniqueEntityVec { + fn as_ref(&self) -> &[T] { + &self.0 + } +} + +impl Borrow<[T]> for UniqueEntityVec { + fn borrow(&self) -> &[T] { + &self.0 + } +} + +impl, U> PartialEq> for UniqueEntityVec { + fn eq(&self, other: &Vec) -> bool { + self.0.eq(other) + } +} + +impl, U> PartialEq<&[U]> for UniqueEntityVec { + fn eq(&self, other: &&[U]) -> bool { + self.0.eq(other) + } +} + +impl, U> PartialEq<&mut [U]> for UniqueEntityVec { + fn eq(&self, other: &&mut [U]) -> bool { + self.0.eq(other) + } +} + +impl, U, const N: usize> PartialEq<&[U; N]> + for UniqueEntityVec +{ + fn eq(&self, other: &&[U; N]) -> bool { + self.0.eq(other) + } +} + +impl, U, const N: usize> PartialEq<&mut [U; N]> + for UniqueEntityVec +{ + fn eq(&self, other: &&mut [U; N]) -> bool { + self.0.eq(&**other) + } +} + +impl, U> PartialEq<[U]> for UniqueEntityVec { + fn eq(&self, other: &[U]) -> bool { + self.0.eq(other) + } +} + +impl, U, const N: usize> PartialEq<[U; N]> + for UniqueEntityVec +{ + fn eq(&self, other: &[U; N]) -> bool { + self.0.eq(other) + } +} + +impl, U: TrustedEntityBorrow> PartialEq> for Vec { + fn eq(&self, other: &UniqueEntityVec) -> bool { + self.eq(&other.0) + } +} + +impl, U: TrustedEntityBorrow> PartialEq> for &[T] { + fn eq(&self, other: &UniqueEntityVec) -> bool { + self.eq(&other.0) + } +} + +impl, U: TrustedEntityBorrow> PartialEq> for &mut [T] { + fn eq(&self, other: &UniqueEntityVec) -> bool { + self.eq(&other.0) + } +} + +impl, U: TrustedEntityBorrow> PartialEq> + for [T] +{ + fn eq(&self, other: &UniqueEntityVec) -> bool { + self.eq(&other.0) + } +} + +impl + Clone, U: TrustedEntityBorrow> PartialEq> + for Cow<'_, [T]> +{ + fn eq(&self, other: &UniqueEntityVec) -> bool { + self.eq(&other.0) + } +} + +impl, U: TrustedEntityBorrow> PartialEq> for VecDeque { + fn eq(&self, other: &UniqueEntityVec) -> bool { + self.eq(&other.0) + } +} + +impl From<&[T; 1]> for UniqueEntityVec { + fn from(value: &[T; 1]) -> Self { + Self(Vec::from(value)) + } +} + +impl From<&[T; 0]> for UniqueEntityVec { + fn from(value: &[T; 0]) -> Self { + Self(Vec::from(value)) + } +} + +impl From<&mut [T; 1]> for UniqueEntityVec { + fn from(value: &mut [T; 1]) -> Self { + Self(Vec::from(value)) + } +} + +impl From<&mut [T; 0]> for UniqueEntityVec { + fn from(value: &mut [T; 0]) -> Self { + Self(Vec::from(value)) + } +} + +impl From<[T; 1]> for UniqueEntityVec { + fn from(value: [T; 1]) -> Self { + Self(Vec::from(value)) + } +} + +impl From<[T; 0]> for UniqueEntityVec { + fn from(value: [T; 0]) -> Self { + Self(Vec::from(value)) + } +} + +impl From> for Vec { + fn from(value: UniqueEntityVec) -> Self { + value.0 + } +} + +impl<'a, T: TrustedEntityBorrow + Clone> From> for Cow<'a, [T]> { + fn from(value: UniqueEntityVec) -> Self { + Cow::from(value.0) + } +} + +impl From> for Arc<[T]> { + fn from(value: UniqueEntityVec) -> Self { + Arc::from(value.0) + } +} + +impl From> for BinaryHeap { + fn from(value: UniqueEntityVec) -> Self { + BinaryHeap::from(value.0) + } +} + +impl From> for Box<[T]> { + fn from(value: UniqueEntityVec) -> Self { + Box::from(value.0) + } +} + +impl From> for Rc<[T]> { + fn from(value: UniqueEntityVec) -> Self { + Rc::from(value.0) + } +} + +impl From> for VecDeque { + fn from(value: UniqueEntityVec) -> Self { + VecDeque::from(value.0) + } +} + +impl TryFrom> for Box<[T; N]> { + type Error = UniqueEntityVec; + + fn try_from(value: UniqueEntityVec) -> Result { + Box::try_from(value.0).map_err(UniqueEntityVec) + } +} + +impl TryFrom> for [T; N] { + type Error = UniqueEntityVec; + + fn try_from(value: UniqueEntityVec) -> Result { + <[T; N] as TryFrom>>::try_from(value.0).map_err(UniqueEntityVec) + } +} + +impl From> for UniqueEntityVec { + fn from(value: BTreeSet) -> Self { + Self(value.into_iter().collect::>()) + } +} + +impl FromIterator for UniqueEntityVec { + /// This impl only uses `Eq` to validate uniqueness, resulting in O(n^2) complexity. + /// It can make sense for very low N, or if `T` implements neither `Ord` nor `Hash`. + /// When possible, use `FromEntitySetIterator::from_entity_iter` instead. + fn from_iter>(iter: I) -> Self { + // Matches the `HashSet::from_iter` reservation logic. + let iter = iter.into_iter(); + let unique_vec = Self::with_capacity(iter.size_hint().0); + // Internal iteration (fold/for_each) is known to result in better code generation + // over a for loop. + iter.fold(unique_vec, |mut unique_vec, item| { + if !unique_vec.0.contains(&item) { + unique_vec.0.push(item); + } + unique_vec + }) + } +} + +impl FromEntitySetIterator for UniqueEntityVec { + fn from_entity_set_iter>(iter: I) -> Self { + // SAFETY: `iter` is an `EntitySet`. + unsafe { Self::from_vec_unchecked(Vec::from_iter(iter)) } + } +} + +impl Extend for UniqueEntityVec { + /// Use with caution, because this impl only uses `Eq` to validate uniqueness, + /// resulting in O(n^2) complexity. + /// It can make sense for very low N, or if `T` implements neither `Ord` nor `Hash`. + fn extend>(&mut self, iter: I) { + // Matches the `HashSet::extend` reservation logic. Their reasoning: + // "Keys may be already present or show multiple times in the iterator. + // Reserve the entire hint lower bound if the map is empty. + // Otherwise reserve half the hint (rounded up), so the map + // will only resize twice in the worst case." + let iter = iter.into_iter(); + let reserve = if self.is_empty() { + iter.size_hint().0 + } else { + (iter.size_hint().0 + 1) / 2 + }; + self.reserve(reserve); + // Internal iteration (fold/for_each) is known to result in better code generation + // over a for loop. + iter.for_each(move |item| { + if !self.0.contains(&item) { + self.0.push(item); + } + }); + } +} + +impl<'a, T: TrustedEntityBorrow + Copy + 'a> Extend<&'a T> for UniqueEntityVec { + /// Use with caution, because this impl only uses `Eq` to validate uniqueness, + /// resulting in O(n^2) complexity. + /// It can make sense for very low N, or if `T` implements neither `Ord` nor `Hash`. + fn extend>(&mut self, iter: I) { + // Matches the `HashSet::extend` reservation logic. Their reasoning: + // "Keys may be already present or show multiple times in the iterator. + // Reserve the entire hint lower bound if the map is empty. + // Otherwise reserve half the hint (rounded up), so the map + // will only resize twice in the worst case." + let iter = iter.into_iter(); + let reserve = if self.is_empty() { + iter.size_hint().0 + } else { + (iter.size_hint().0 + 1) / 2 + }; + self.reserve(reserve); + // Internal iteration (fold/for_each) is known to result in better code generation + // over a for loop. + iter.for_each(move |item| { + if !self.0.contains(item) { + self.0.push(*item); + } + }); + } +} + +impl Index for UniqueEntityVec { + type Output = T; + fn index(&self, key: usize) -> &T { + self.0.index(key) + } +} + +/// A draining iterator for [`UniqueEntityVec`]. +/// +/// This struct is created by [`UniqueEntityVec::drain`]. +/// See its documentation for more. +pub type Drain<'a, T> = UniqueEntityIter>; + +/// A splicing iterator for [`UniqueEntityVec`]. +/// +/// This struct is created by [`UniqueEntityVec::splice`]. +/// See its documentation for more. +pub type Splice<'a, I> = UniqueEntityIter>; + +/// An iterator that moves out of a vector. +/// +/// This `struct` is created by the [`IntoIterator::into_iter`] trait +/// method on [`UniqueEntityVec`]. +pub type IntoIter = UniqueEntityIter>;