wrap EntityIndexMap/Set slices as well (#18134)
# Objective Continuation of #17449. #17449 implemented the wrapper types around `IndexMap`/`Set` and co., however punted on the slice types. They are needed to support creating `EntitySetIterator`s from their slices, not just the base maps and sets. ## Solution Add the wrappers, in the same vein as #17449 and #17589 before. The `Index`/`IndexMut` implementations take up a lot of space, however they cannot be merged because we'd then get overlaps. They are simply named `Slice` to match the `indexmap` naming scheme, but this means they cannot be differentiated properly until their modules are made public, which is already a follow-up mentioned in #17954.
This commit is contained in:
parent
9b32e09551
commit
d229475a3f
@ -3,19 +3,26 @@
|
||||
//! This module is a lightweight wrapper around `indexmap`'s [`IndexMap`] that is more performant for [`Entity`] keys.
|
||||
|
||||
use core::{
|
||||
cmp::Ordering,
|
||||
fmt::{self, Debug, Formatter},
|
||||
hash::BuildHasher,
|
||||
hash::{BuildHasher, Hash, Hasher},
|
||||
iter::FusedIterator,
|
||||
marker::PhantomData,
|
||||
ops::{Deref, DerefMut, Index, IndexMut, RangeBounds},
|
||||
ops::{
|
||||
Bound, Deref, DerefMut, Index, IndexMut, Range, RangeBounds, RangeFrom, RangeFull,
|
||||
RangeInclusive, RangeTo, RangeToInclusive,
|
||||
},
|
||||
ptr,
|
||||
};
|
||||
|
||||
#[cfg(feature = "bevy_reflect")]
|
||||
use bevy_reflect::Reflect;
|
||||
use indexmap::map::{self, IndexMap};
|
||||
use indexmap::map::{self, IndexMap, IntoValues, ValuesMut};
|
||||
|
||||
use super::{Entity, EntityHash, EntitySetIterator, TrustedEntityBorrow};
|
||||
|
||||
use bevy_platform_support::prelude::Box;
|
||||
|
||||
/// A [`IndexMap`] pre-configured to use [`EntityHash`] hashing.
|
||||
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
|
||||
@ -46,6 +53,48 @@ impl<V> EntityIndexMap<V> {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Returns a slice of all the key-value pairs in the map.
|
||||
///
|
||||
/// Equivalent to [`IndexMap::as_slice`].
|
||||
pub fn as_slice(&self) -> &Slice<V> {
|
||||
// SAFETY: Slice is a transparent wrapper around indexmap::map::Slice.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.as_slice()) }
|
||||
}
|
||||
|
||||
/// Returns a mutable slice of all the key-value pairs in the map.
|
||||
///
|
||||
/// Equivalent to [`IndexMap::as_mut_slice`].
|
||||
pub fn as_mut_slice(&mut self) -> &mut Slice<V> {
|
||||
// SAFETY: Slice is a transparent wrapper around indexmap::map::Slice.
|
||||
unsafe { Slice::from_slice_unchecked_mut(self.0.as_mut_slice()) }
|
||||
}
|
||||
|
||||
/// Converts into a boxed slice of all the key-value pairs in the map.
|
||||
///
|
||||
/// Equivalent to [`IndexMap::into_boxed_slice`].
|
||||
pub fn into_boxed_slice(self) -> Box<Slice<V>> {
|
||||
// SAFETY: Slice is a transparent wrapper around indexmap::map::Slice.
|
||||
unsafe { Slice::from_boxed_slice_unchecked(self.0.into_boxed_slice()) }
|
||||
}
|
||||
|
||||
/// Returns a slice of key-value pairs in the given range of indices.
|
||||
///
|
||||
/// Equivalent to [`IndexMap::get_range`].
|
||||
pub fn get_range<R: RangeBounds<usize>>(&self, range: R) -> Option<&Slice<V>> {
|
||||
self.0.get_range(range).map(|slice|
|
||||
// SAFETY: EntityIndexSetSlice is a transparent wrapper around indexmap::set::Slice.
|
||||
unsafe { Slice::from_slice_unchecked(slice) })
|
||||
}
|
||||
|
||||
/// Returns a mutable slice of key-value pairs in the given range of indices.
|
||||
///
|
||||
/// Equivalent to [`IndexMap::get_range_mut`].
|
||||
pub fn get_range_mut<R: RangeBounds<usize>>(&mut self, range: R) -> Option<&mut Slice<V>> {
|
||||
self.0.get_range_mut(range).map(|slice|
|
||||
// SAFETY: EntityIndexSetSlice is a transparent wrapper around indexmap::set::Slice.
|
||||
unsafe { Slice::from_slice_unchecked_mut(slice) })
|
||||
}
|
||||
|
||||
/// Return an iterator over the key-value pairs of the map, in their order.
|
||||
///
|
||||
/// Equivalent to [`IndexMap::iter`].
|
||||
@ -134,6 +183,62 @@ impl<V, Q: TrustedEntityBorrow + ?Sized> Index<&Q> for EntityIndexMap<V> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<(Bound<usize>, Bound<usize>)> for EntityIndexMap<V> {
|
||||
type Output = Slice<V>;
|
||||
fn index(&self, key: (Bound<usize>, Bound<usize>)) -> &Self::Output {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<Range<usize>> for EntityIndexMap<V> {
|
||||
type Output = Slice<V>;
|
||||
fn index(&self, key: Range<usize>) -> &Self::Output {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<RangeFrom<usize>> for EntityIndexMap<V> {
|
||||
type Output = Slice<V>;
|
||||
fn index(&self, key: RangeFrom<usize>) -> &Self::Output {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<RangeFull> for EntityIndexMap<V> {
|
||||
type Output = Slice<V>;
|
||||
fn index(&self, key: RangeFull) -> &Self::Output {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<RangeInclusive<usize>> for EntityIndexMap<V> {
|
||||
type Output = Slice<V>;
|
||||
fn index(&self, key: RangeInclusive<usize>) -> &Self::Output {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<RangeTo<usize>> for EntityIndexMap<V> {
|
||||
type Output = Slice<V>;
|
||||
fn index(&self, key: RangeTo<usize>) -> &Self::Output {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<RangeToInclusive<usize>> for EntityIndexMap<V> {
|
||||
type Output = Slice<V>;
|
||||
fn index(&self, key: RangeToInclusive<usize>) -> &Self::Output {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<usize> for EntityIndexMap<V> {
|
||||
type Output = V;
|
||||
fn index(&self, key: usize) -> &V {
|
||||
@ -147,6 +252,55 @@ impl<V, Q: TrustedEntityBorrow + ?Sized> IndexMut<&Q> for EntityIndexMap<V> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IndexMut<(Bound<usize>, Bound<usize>)> for EntityIndexMap<V> {
|
||||
fn index_mut(&mut self, key: (Bound<usize>, Bound<usize>)) -> &mut Self::Output {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked_mut(self.0.index_mut(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IndexMut<Range<usize>> for EntityIndexMap<V> {
|
||||
fn index_mut(&mut self, key: Range<usize>) -> &mut Self::Output {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked_mut(self.0.index_mut(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IndexMut<RangeFrom<usize>> for EntityIndexMap<V> {
|
||||
fn index_mut(&mut self, key: RangeFrom<usize>) -> &mut Self::Output {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked_mut(self.0.index_mut(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IndexMut<RangeFull> for EntityIndexMap<V> {
|
||||
fn index_mut(&mut self, key: RangeFull) -> &mut Self::Output {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked_mut(self.0.index_mut(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IndexMut<RangeInclusive<usize>> for EntityIndexMap<V> {
|
||||
fn index_mut(&mut self, key: RangeInclusive<usize>) -> &mut Self::Output {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked_mut(self.0.index_mut(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IndexMut<RangeTo<usize>> for EntityIndexMap<V> {
|
||||
fn index_mut(&mut self, key: RangeTo<usize>) -> &mut Self::Output {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked_mut(self.0.index_mut(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IndexMut<RangeToInclusive<usize>> for EntityIndexMap<V> {
|
||||
fn index_mut(&mut self, key: RangeToInclusive<usize>) -> &mut Self::Output {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked_mut(self.0.index_mut(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IndexMut<usize> for EntityIndexMap<V> {
|
||||
fn index_mut(&mut self, key: usize) -> &mut V {
|
||||
self.0.index_mut(key)
|
||||
@ -201,6 +355,476 @@ where
|
||||
|
||||
impl<V: Eq> Eq for EntityIndexMap<V> {}
|
||||
|
||||
/// A dynamically-sized slice of key-value pairs in an [`EntityIndexMap`].
|
||||
///
|
||||
/// Equivalent to an [`indexmap::map::Slice<V>`] whose source [`IndexMap`]
|
||||
/// uses [`EntityHash`].
|
||||
#[repr(transparent)]
|
||||
pub struct Slice<V, S = EntityHash>(PhantomData<S>, map::Slice<Entity, V>);
|
||||
|
||||
impl<V> Slice<V> {
|
||||
/// Returns an empty slice.
|
||||
///
|
||||
/// Equivalent to [`map::Slice::new`].
|
||||
pub const fn new<'a>() -> &'a Self {
|
||||
// SAFETY: The source slice is empty.
|
||||
unsafe { Self::from_slice_unchecked(map::Slice::new()) }
|
||||
}
|
||||
|
||||
/// Returns an empty mutable slice.
|
||||
///
|
||||
/// Equivalent to [`map::Slice::new_mut`].
|
||||
pub fn new_mut<'a>() -> &'a mut Self {
|
||||
// SAFETY: The source slice is empty.
|
||||
unsafe { Self::from_slice_unchecked_mut(map::Slice::new_mut()) }
|
||||
}
|
||||
|
||||
/// Constructs a [`entity::index_map::Slice`] from a [`indexmap::map::Slice`] unsafely.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `slice` must stem from an [`IndexMap`] using [`EntityHash`].
|
||||
///
|
||||
/// [`entity::index_map::Slice`]: `crate::entity::index_map::Slice`
|
||||
pub const unsafe fn from_slice_unchecked(slice: &map::Slice<Entity, V>) -> &Self {
|
||||
// SAFETY: Slice is a transparent wrapper around indexmap::map::Slice.
|
||||
unsafe { &*(ptr::from_ref(slice) as *const Self) }
|
||||
}
|
||||
|
||||
/// Constructs a [`entity::index_map::Slice`] from a [`indexmap::map::Slice`] unsafely.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `slice` must stem from an [`IndexMap`] using [`EntityHash`].
|
||||
///
|
||||
/// [`entity::index_map::Slice`]: `crate::entity::index_map::Slice`
|
||||
pub const unsafe fn from_slice_unchecked_mut(slice: &mut map::Slice<Entity, V>) -> &mut Self {
|
||||
// SAFETY: Slice is a transparent wrapper around indexmap::map::Slice.
|
||||
unsafe { &mut *(ptr::from_mut(slice) as *mut Self) }
|
||||
}
|
||||
|
||||
/// Casts `self` to the inner slice.
|
||||
pub const fn as_inner(&self) -> &map::Slice<Entity, V> {
|
||||
&self.1
|
||||
}
|
||||
|
||||
/// Constructs a boxed [`entity::index_map::Slice`] from a boxed [`indexmap::map::Slice`] unsafely.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `slice` must stem from an [`IndexMap`] using [`EntityHash`].
|
||||
///
|
||||
/// [`entity::index_map::Slice`]: `crate::entity::index_map::Slice`
|
||||
pub unsafe fn from_boxed_slice_unchecked(slice: Box<map::Slice<Entity, V>>) -> Box<Self> {
|
||||
// SAFETY: Slice is a transparent wrapper around indexmap::map::Slice.
|
||||
unsafe { Box::from_raw(Box::into_raw(slice) as *mut Self) }
|
||||
}
|
||||
|
||||
/// Casts a reference to `self` to the inner slice.
|
||||
#[expect(
|
||||
clippy::borrowed_box,
|
||||
reason = "We wish to access the Box API of the inner type, without consuming it."
|
||||
)]
|
||||
pub fn as_boxed_inner(self: &Box<Self>) -> &Box<map::Slice<Entity, V>> {
|
||||
// SAFETY: Slice is a transparent wrapper around indexmap::map::Slice.
|
||||
unsafe { &*(ptr::from_ref(self).cast::<Box<map::Slice<Entity, V>>>()) }
|
||||
}
|
||||
|
||||
/// Casts `self` to the inner slice.
|
||||
pub fn into_boxed_inner(self: Box<Self>) -> Box<map::Slice<Entity, V>> {
|
||||
// SAFETY: Slice is a transparent wrapper around indexmap::map::Slice.
|
||||
unsafe { Box::from_raw(Box::into_raw(self) as *mut map::Slice<Entity, V>) }
|
||||
}
|
||||
|
||||
/// Get a key-value pair by index, with mutable access to the value.
|
||||
///
|
||||
/// Equivalent to [`map::Slice::get_index_mut`].
|
||||
pub fn get_index_mut(&mut self, index: usize) -> Option<(&Entity, &mut V)> {
|
||||
self.1.get_index_mut(index)
|
||||
}
|
||||
|
||||
/// Returns a slice of key-value pairs in the given range of indices.
|
||||
///
|
||||
/// Equivalent to [`map::Slice::get_range`].
|
||||
pub fn get_range<R: RangeBounds<usize>>(&self, range: R) -> Option<&Self> {
|
||||
self.1.get_range(range).map(|slice|
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(slice) })
|
||||
}
|
||||
|
||||
/// Returns a mutable slice of key-value pairs in the given range of indices.
|
||||
///
|
||||
/// Equivalent to [`map::Slice::get_range_mut`].
|
||||
pub fn get_range_mut<R: RangeBounds<usize>>(&mut self, range: R) -> Option<&mut Self> {
|
||||
self.1.get_range_mut(range).map(|slice|
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked_mut(slice) })
|
||||
}
|
||||
|
||||
/// Get the first key-value pair, with mutable access to the value.
|
||||
///
|
||||
/// Equivalent to [`map::Slice::first_mut`].
|
||||
pub fn first_mut(&mut self) -> Option<(&Entity, &mut V)> {
|
||||
self.1.first_mut()
|
||||
}
|
||||
|
||||
/// Get the last key-value pair, with mutable access to the value.
|
||||
///
|
||||
/// Equivalent to [`map::Slice::last_mut`].
|
||||
pub fn last_mut(&mut self) -> Option<(&Entity, &mut V)> {
|
||||
self.1.last_mut()
|
||||
}
|
||||
|
||||
/// Divides one slice into two at an index.
|
||||
///
|
||||
/// Equivalent to [`map::Slice::split_at`].
|
||||
pub fn split_at(&self, index: usize) -> (&Self, &Self) {
|
||||
let (slice_1, slice_2) = self.1.split_at(index);
|
||||
// SAFETY: These are subslices of a valid slice.
|
||||
unsafe {
|
||||
(
|
||||
Self::from_slice_unchecked(slice_1),
|
||||
Self::from_slice_unchecked(slice_2),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Divides one mutable slice into two at an index.
|
||||
///
|
||||
/// Equivalent to [`map::Slice::split_at_mut`].
|
||||
pub fn split_at_mut(&mut self, index: usize) -> (&mut Self, &mut Self) {
|
||||
let (slice_1, slice_2) = self.1.split_at_mut(index);
|
||||
// SAFETY: These are subslices of a valid slice.
|
||||
unsafe {
|
||||
(
|
||||
Self::from_slice_unchecked_mut(slice_1),
|
||||
Self::from_slice_unchecked_mut(slice_2),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the first key-value pair and the rest of the slice,
|
||||
/// or `None` if it is empty.
|
||||
///
|
||||
/// Equivalent to [`map::Slice::split_first`].
|
||||
pub fn split_first(&self) -> Option<((&Entity, &V), &Self)> {
|
||||
self.1.split_first().map(|(first, rest)| {
|
||||
(
|
||||
first,
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(rest) },
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the first key-value pair and the rest of the slice,
|
||||
/// with mutable access to the value, or `None` if it is empty.
|
||||
///
|
||||
/// Equivalent to [`map::Slice::split_first_mut`].
|
||||
pub fn split_first_mut(&mut self) -> Option<((&Entity, &mut V), &mut Self)> {
|
||||
self.1.split_first_mut().map(|(first, rest)| {
|
||||
(
|
||||
first,
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked_mut(rest) },
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the last key-value pair and the rest of the slice,
|
||||
/// or `None` if it is empty.
|
||||
///
|
||||
/// Equivalent to [`map::Slice::split_last`].
|
||||
pub fn split_last(&self) -> Option<((&Entity, &V), &Self)> {
|
||||
self.1.split_last().map(|(last, rest)| {
|
||||
(
|
||||
last,
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(rest) },
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the last key-value pair and the rest of the slice,
|
||||
/// with mutable access to the value, or `None` if it is empty.
|
||||
///
|
||||
/// Equivalent to [`map::Slice::split_last_mut`].
|
||||
pub fn split_last_mut(&mut self) -> Option<((&Entity, &mut V), &mut Self)> {
|
||||
self.1.split_last_mut().map(|(last, rest)| {
|
||||
(
|
||||
last,
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked_mut(rest) },
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// Return an iterator over the key-value pairs of the map slice.
|
||||
///
|
||||
/// Equivalent to [`map::Slice::iter`].
|
||||
pub fn iter(&self) -> Iter<'_, V> {
|
||||
Iter(self.1.iter(), PhantomData)
|
||||
}
|
||||
|
||||
/// Return an iterator over the key-value pairs of the map slice.
|
||||
///
|
||||
/// Equivalent to [`map::Slice::iter_mut`].
|
||||
pub fn iter_mut(&mut self) -> IterMut<'_, V> {
|
||||
IterMut(self.1.iter_mut(), PhantomData)
|
||||
}
|
||||
|
||||
/// Return an iterator over the keys of the map slice.
|
||||
///
|
||||
/// Equivalent to [`map::Slice::keys`].
|
||||
pub fn keys(&self) -> Keys<'_, V> {
|
||||
Keys(self.1.keys(), PhantomData)
|
||||
}
|
||||
|
||||
/// Return an owning iterator over the keys of the map slice.
|
||||
///
|
||||
/// Equivalent to [`map::Slice::into_keys`].
|
||||
pub fn into_keys(self: Box<Self>) -> IntoKeys<V> {
|
||||
IntoKeys(self.into_boxed_inner().into_keys(), PhantomData)
|
||||
}
|
||||
|
||||
/// Return an iterator over mutable references to the the values of the map slice.
|
||||
///
|
||||
/// Equivalent to [`map::Slice::values_mut`].
|
||||
pub fn values_mut(&mut self) -> ValuesMut<'_, Entity, V> {
|
||||
self.1.values_mut()
|
||||
}
|
||||
|
||||
/// Return an owning iterator over the values of the map slice.
|
||||
///
|
||||
/// Equivalent to [`map::Slice::into_values`].
|
||||
pub fn into_values(self: Box<Self>) -> IntoValues<Entity, V> {
|
||||
self.into_boxed_inner().into_values()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Deref for Slice<V> {
|
||||
type Target = map::Slice<Entity, V>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.1
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Debug> Debug for Slice<V> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Slice")
|
||||
.field(&self.0)
|
||||
.field(&&self.1)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Clone> Clone for Box<Slice<V>> {
|
||||
fn clone(&self) -> Self {
|
||||
// SAFETY: This a clone of a valid slice.
|
||||
unsafe { Slice::from_boxed_slice_unchecked(self.as_boxed_inner().clone()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Default for &Slice<V> {
|
||||
fn default() -> Self {
|
||||
// SAFETY: The source slice is empty.
|
||||
unsafe { Slice::from_slice_unchecked(<&map::Slice<Entity, V>>::default()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Default for &mut Slice<V> {
|
||||
fn default() -> Self {
|
||||
// SAFETY: The source slice is empty.
|
||||
unsafe { Slice::from_slice_unchecked_mut(<&mut map::Slice<Entity, V>>::default()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Default for Box<Slice<V>> {
|
||||
fn default() -> Self {
|
||||
// SAFETY: The source slice is empty.
|
||||
unsafe { Slice::from_boxed_slice_unchecked(<Box<map::Slice<Entity, V>>>::default()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Copy> From<&Slice<V>> for Box<Slice<V>> {
|
||||
fn from(value: &Slice<V>) -> Self {
|
||||
// SAFETY: This slice is a copy of a valid slice.
|
||||
unsafe { Slice::from_boxed_slice_unchecked(value.1.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Hash> Hash for Slice<V> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.1.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V> IntoIterator for &'a Slice<V> {
|
||||
type Item = (&'a Entity, &'a V);
|
||||
type IntoIter = Iter<'a, V>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
Iter(self.1.iter(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V> IntoIterator for &'a mut Slice<V> {
|
||||
type Item = (&'a Entity, &'a mut V);
|
||||
type IntoIter = IterMut<'a, V>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
IterMut(self.1.iter_mut(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IntoIterator for Box<Slice<V>> {
|
||||
type Item = (Entity, V);
|
||||
type IntoIter = IntoIter<V>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
IntoIter(self.into_boxed_inner().into_iter(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: PartialOrd> PartialOrd for Slice<V> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
self.1.partial_cmp(&other.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Ord> Ord for Slice<V> {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.1.cmp(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: PartialEq> PartialEq for Slice<V> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.1 == other.1
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Eq> Eq for Slice<V> {}
|
||||
|
||||
impl<V> Index<(Bound<usize>, Bound<usize>)> for Slice<V> {
|
||||
type Output = Self;
|
||||
fn index(&self, key: (Bound<usize>, Bound<usize>)) -> &Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(self.1.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<Range<usize>> for Slice<V> {
|
||||
type Output = Self;
|
||||
fn index(&self, key: Range<usize>) -> &Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(self.1.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<RangeFrom<usize>> for Slice<V> {
|
||||
type Output = Self;
|
||||
fn index(&self, key: RangeFrom<usize>) -> &Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(self.1.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<RangeFull> for Slice<V> {
|
||||
type Output = Self;
|
||||
fn index(&self, key: RangeFull) -> &Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(self.1.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<RangeInclusive<usize>> for Slice<V> {
|
||||
type Output = Self;
|
||||
fn index(&self, key: RangeInclusive<usize>) -> &Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(self.1.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<RangeTo<usize>> for Slice<V> {
|
||||
type Output = Self;
|
||||
fn index(&self, key: RangeTo<usize>) -> &Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(self.1.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<RangeToInclusive<usize>> for Slice<V> {
|
||||
type Output = Self;
|
||||
fn index(&self, key: RangeToInclusive<usize>) -> &Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(self.1.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Index<usize> for Slice<V> {
|
||||
type Output = V;
|
||||
fn index(&self, key: usize) -> &V {
|
||||
self.1.index(key)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IndexMut<(Bound<usize>, Bound<usize>)> for Slice<V> {
|
||||
fn index_mut(&mut self, key: (Bound<usize>, Bound<usize>)) -> &mut Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked_mut(self.1.index_mut(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IndexMut<Range<usize>> for Slice<V> {
|
||||
fn index_mut(&mut self, key: Range<usize>) -> &mut Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked_mut(self.1.index_mut(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IndexMut<RangeFrom<usize>> for Slice<V> {
|
||||
fn index_mut(&mut self, key: RangeFrom<usize>) -> &mut Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked_mut(self.1.index_mut(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IndexMut<RangeFull> for Slice<V> {
|
||||
fn index_mut(&mut self, key: RangeFull) -> &mut Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked_mut(self.1.index_mut(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IndexMut<RangeInclusive<usize>> for Slice<V> {
|
||||
fn index_mut(&mut self, key: RangeInclusive<usize>) -> &mut Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked_mut(self.1.index_mut(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IndexMut<RangeTo<usize>> for Slice<V> {
|
||||
fn index_mut(&mut self, key: RangeTo<usize>) -> &mut Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked_mut(self.1.index_mut(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IndexMut<RangeToInclusive<usize>> for Slice<V> {
|
||||
fn index_mut(&mut self, key: RangeToInclusive<usize>) -> &mut Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked_mut(self.1.index_mut(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> IndexMut<usize> for Slice<V> {
|
||||
fn index_mut(&mut self, key: usize) -> &mut V {
|
||||
self.1.index_mut(key)
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the entries of an [`EntityIndexMap`].
|
||||
///
|
||||
/// This `struct` is created by the [`EntityIndexMap::iter`] method.
|
||||
@ -212,6 +836,14 @@ impl<'a, V> Iter<'a, V> {
|
||||
pub fn into_inner(self) -> map::Iter<'a, Entity, V> {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Returns a slice of the remaining entries in the iterator.
|
||||
///
|
||||
/// Equivalent to [`map::Iter::as_slice`].
|
||||
pub fn as_slice(&self) -> &Slice<V> {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.as_slice()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V> Deref for Iter<'a, V> {
|
||||
@ -269,6 +901,22 @@ impl<'a, V> IterMut<'a, V> {
|
||||
pub fn into_inner(self) -> map::IterMut<'a, Entity, V> {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Returns a slice of the remaining entries in the iterator.
|
||||
///
|
||||
/// Equivalent to [`map::IterMut::as_slice`].
|
||||
pub fn as_slice(&self) -> &Slice<V> {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.as_slice()) }
|
||||
}
|
||||
|
||||
/// Returns a mutable slice of the remaining entries in the iterator.
|
||||
///
|
||||
/// Equivalent to [`map::IterMut::into_slice`].
|
||||
pub fn into_slice(self) -> &'a mut Slice<V> {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked_mut(self.0.into_slice()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V> Deref for IterMut<'a, V> {
|
||||
@ -323,6 +971,22 @@ impl<V> IntoIter<V> {
|
||||
pub fn into_inner(self) -> map::IntoIter<Entity, V> {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Returns a slice of the remaining entries in the iterator.
|
||||
///
|
||||
/// Equivalent to [`map::IntoIter::as_slice`].
|
||||
pub fn as_slice(&self) -> &Slice<V> {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.as_slice()) }
|
||||
}
|
||||
|
||||
/// Returns a mutable slice of the remaining entries in the iterator.
|
||||
///
|
||||
/// Equivalent to [`map::IntoIter::as_mut_slice`].
|
||||
pub fn as_mut_slice(&mut self) -> &mut Slice<V> {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked_mut(self.0.as_mut_slice()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Deref for IntoIter<V> {
|
||||
@ -383,6 +1047,14 @@ impl<'a, V> Drain<'a, V> {
|
||||
pub fn into_inner(self) -> map::Drain<'a, Entity, V> {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Returns a slice of the remaining entries in the iterator.
|
||||
///
|
||||
/// Equivalent to [`map::Drain::as_slice`].
|
||||
pub fn as_slice(&self) -> &Slice<V> {
|
||||
// SAFETY: The source IndexMap uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.as_slice()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V> Deref for Drain<'a, V> {
|
||||
|
@ -3,17 +3,25 @@
|
||||
//! This module is a lightweight wrapper around `indexmap`'ss [`IndexSet`] that is more performant for [`Entity`] keys.
|
||||
|
||||
use core::{
|
||||
cmp::Ordering,
|
||||
fmt::{self, Debug, Formatter},
|
||||
hash::BuildHasher,
|
||||
hash::{Hash, Hasher},
|
||||
iter::FusedIterator,
|
||||
marker::PhantomData,
|
||||
ops::{BitAnd, BitOr, BitXor, Deref, DerefMut, Index, RangeBounds, Sub},
|
||||
ops::{
|
||||
BitAnd, BitOr, BitXor, Bound, Deref, DerefMut, Index, Range, RangeBounds, RangeFrom,
|
||||
RangeFull, RangeInclusive, RangeTo, RangeToInclusive, Sub,
|
||||
},
|
||||
ptr,
|
||||
};
|
||||
|
||||
use indexmap::set::{self, IndexSet};
|
||||
|
||||
use super::{Entity, EntityHash, EntitySetIterator};
|
||||
|
||||
use bevy_platform_support::prelude::Box;
|
||||
|
||||
/// An [`IndexSet`] pre-configured to use [`EntityHash`] hashing.
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
@ -43,6 +51,14 @@ impl EntityIndexSet {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Returns a slice of all the values in the set.
|
||||
///
|
||||
/// Equivalent to [`IndexSet::as_slice`].
|
||||
pub fn as_slice(&self) -> &Slice {
|
||||
// SAFETY: Slice is a transparent wrapper around indexmap::set::Slice.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.as_slice()) }
|
||||
}
|
||||
|
||||
/// Clears the `IndexSet` in the given index range, returning those values
|
||||
/// as a drain iterator.
|
||||
///
|
||||
@ -51,12 +67,29 @@ impl EntityIndexSet {
|
||||
Drain(self.0.drain(range), PhantomData)
|
||||
}
|
||||
|
||||
/// Returns a slice of values in the given range of indices.
|
||||
///
|
||||
/// Equivalent to [`IndexSet::get_range`].
|
||||
pub fn get_range<R: RangeBounds<usize>>(&self, range: R) -> Option<&Slice> {
|
||||
self.0.get_range(range).map(|slice|
|
||||
// SAFETY: The source IndexSet uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(slice) })
|
||||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
|
||||
/// Converts into a boxed slice of all the values in the set.
|
||||
///
|
||||
/// Equivalent to [`IndexSet::into_boxed_slice`].
|
||||
pub fn into_boxed_slice(self) -> Box<Slice> {
|
||||
// SAFETY: Slice is a transparent wrapper around indexmap::set::Slice.
|
||||
unsafe { Slice::from_boxed_slice_unchecked(self.0.into_boxed_slice()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for EntityIndexSet {
|
||||
@ -166,6 +199,62 @@ impl PartialEq for EntityIndexSet {
|
||||
|
||||
impl Eq for EntityIndexSet {}
|
||||
|
||||
impl Index<(Bound<usize>, Bound<usize>)> for EntityIndexSet {
|
||||
type Output = Slice;
|
||||
fn index(&self, key: (Bound<usize>, Bound<usize>)) -> &Self::Output {
|
||||
// SAFETY: The source IndexSet uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<Range<usize>> for EntityIndexSet {
|
||||
type Output = Slice;
|
||||
fn index(&self, key: Range<usize>) -> &Self::Output {
|
||||
// SAFETY: The source IndexSet uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<RangeFrom<usize>> for EntityIndexSet {
|
||||
type Output = Slice;
|
||||
fn index(&self, key: RangeFrom<usize>) -> &Self::Output {
|
||||
// SAFETY: The source IndexSet uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<RangeFull> for EntityIndexSet {
|
||||
type Output = Slice;
|
||||
fn index(&self, key: RangeFull) -> &Self::Output {
|
||||
// SAFETY: The source IndexSet uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<RangeInclusive<usize>> for EntityIndexSet {
|
||||
type Output = Slice;
|
||||
fn index(&self, key: RangeInclusive<usize>) -> &Self::Output {
|
||||
// SAFETY: The source IndexSet uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<RangeTo<usize>> for EntityIndexSet {
|
||||
type Output = Slice;
|
||||
fn index(&self, key: RangeTo<usize>) -> &Self::Output {
|
||||
// SAFETY: The source IndexSet uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<RangeToInclusive<usize>> for EntityIndexSet {
|
||||
type Output = Slice;
|
||||
fn index(&self, key: RangeToInclusive<usize>) -> &Self::Output {
|
||||
// SAFETY: The source IndexSet uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for EntityIndexSet {
|
||||
type Output = Entity;
|
||||
fn index(&self, key: usize) -> &Entity {
|
||||
@ -173,6 +262,290 @@ impl Index<usize> for EntityIndexSet {
|
||||
}
|
||||
}
|
||||
|
||||
/// A dynamically-sized slice of values in an [`EntityIndexSet`].
|
||||
///
|
||||
/// Equivalent to an [`indexmap::set::Slice<V>`] whose source [`IndexSet`]
|
||||
/// uses [`EntityHash`].
|
||||
#[repr(transparent)]
|
||||
pub struct Slice<S = EntityHash>(PhantomData<S>, set::Slice<Entity>);
|
||||
|
||||
impl Slice {
|
||||
/// Returns an empty slice.
|
||||
///
|
||||
/// Equivalent to [`set::Slice::new`].
|
||||
pub const fn new<'a>() -> &'a Self {
|
||||
// SAFETY: The source slice is empty.
|
||||
unsafe { Self::from_slice_unchecked(set::Slice::new()) }
|
||||
}
|
||||
|
||||
/// Constructs a [`entity::index_set::Slice`] from a [`indexmap::set::Slice`] unsafely.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `slice` must stem from an [`IndexSet`] using [`EntityHash`].
|
||||
///
|
||||
/// [`entity::index_set::Slice`]: `crate::entity::index_set::Slice`
|
||||
pub const unsafe fn from_slice_unchecked(slice: &set::Slice<Entity>) -> &Self {
|
||||
// SAFETY: Slice is a transparent wrapper around indexmap::set::Slice.
|
||||
unsafe { &*(ptr::from_ref(slice) as *const Self) }
|
||||
}
|
||||
|
||||
/// Constructs a [`entity::index_set::Slice`] from a [`indexmap::set::Slice`] unsafely.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `slice` must stem from an [`IndexSet`] using [`EntityHash`].
|
||||
///
|
||||
/// [`entity::index_set::Slice`]: `crate::entity::index_set::Slice`
|
||||
pub const unsafe fn from_slice_unchecked_mut(slice: &mut set::Slice<Entity>) -> &mut Self {
|
||||
// SAFETY: Slice is a transparent wrapper around indexmap::set::Slice.
|
||||
unsafe { &mut *(ptr::from_mut(slice) as *mut Self) }
|
||||
}
|
||||
|
||||
/// Casts `self` to the inner slice.
|
||||
pub const fn as_inner(&self) -> &set::Slice<Entity> {
|
||||
&self.1
|
||||
}
|
||||
|
||||
/// Constructs a boxed [`entity::index_set::Slice`] from a boxed [`indexmap::set::Slice`] unsafely.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `slice` must stem from an [`IndexSet`] using [`EntityHash`].
|
||||
///
|
||||
/// [`entity::index_set::Slice`]: `crate::entity::index_set::Slice`
|
||||
pub unsafe fn from_boxed_slice_unchecked(slice: Box<set::Slice<Entity>>) -> Box<Self> {
|
||||
// SAFETY: Slice is a transparent wrapper around indexmap::set::Slice.
|
||||
unsafe { Box::from_raw(Box::into_raw(slice) as *mut Self) }
|
||||
}
|
||||
|
||||
/// Casts a reference to `self` to the inner slice.
|
||||
#[expect(
|
||||
clippy::borrowed_box,
|
||||
reason = "We wish to access the Box API of the inner type, without consuming it."
|
||||
)]
|
||||
pub fn as_boxed_inner(self: &Box<Self>) -> &Box<set::Slice<Entity>> {
|
||||
// SAFETY: Slice is a transparent wrapper around indexmap::set::Slice.
|
||||
unsafe { &*(ptr::from_ref(self).cast::<Box<set::Slice<Entity>>>()) }
|
||||
}
|
||||
|
||||
/// Casts `self` to the inner slice.
|
||||
pub fn into_boxed_inner(self: Box<Self>) -> Box<set::Slice<Entity>> {
|
||||
// SAFETY: Slice is a transparent wrapper around indexmap::set::Slice.
|
||||
unsafe { Box::from_raw(Box::into_raw(self) as *mut set::Slice<Entity>) }
|
||||
}
|
||||
|
||||
/// Returns a slice of values in the given range of indices.
|
||||
///
|
||||
/// Equivalent to [`set::Slice::get_range`].
|
||||
pub fn get_range<R: RangeBounds<usize>>(&self, range: R) -> Option<&Self> {
|
||||
self.1.get_range(range).map(|slice|
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(slice) })
|
||||
}
|
||||
|
||||
/// Divides one slice into two at an index.
|
||||
///
|
||||
/// Equivalent to [`set::Slice::split_at`].
|
||||
pub fn split_at(&self, index: usize) -> (&Self, &Self) {
|
||||
let (slice_1, slice_2) = self.1.split_at(index);
|
||||
// SAFETY: These are subslices of a valid slice.
|
||||
unsafe {
|
||||
(
|
||||
Self::from_slice_unchecked(slice_1),
|
||||
Self::from_slice_unchecked(slice_2),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the first value and the rest of the slice,
|
||||
/// or `None` if it is empty.
|
||||
///
|
||||
/// Equivalent to [`set::Slice::split_first`].
|
||||
pub fn split_first(&self) -> Option<(&Entity, &Self)> {
|
||||
self.1.split_first().map(|(first, rest)| {
|
||||
(
|
||||
first,
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(rest) },
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the last value and the rest of the slice,
|
||||
/// or `None` if it is empty.
|
||||
///
|
||||
/// Equivalent to [`set::Slice::split_last`].
|
||||
pub fn split_last(&self) -> Option<(&Entity, &Self)> {
|
||||
self.1.split_last().map(|(last, rest)| {
|
||||
(
|
||||
last,
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(rest) },
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// Return an iterator over the values of the set slice.
|
||||
///
|
||||
/// Equivalent to [`set::Slice::iter`].
|
||||
pub fn iter(&self) -> Iter<'_> {
|
||||
Iter(self.1.iter(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Slice {
|
||||
type Target = set::Slice<Entity>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.1
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a Slice {
|
||||
type IntoIter = Iter<'a>;
|
||||
type Item = &'a Entity;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for Box<Slice> {
|
||||
type IntoIter = IntoIter;
|
||||
type Item = Entity;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
IntoIter(self.into_boxed_inner().into_iter(), PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Box<Slice> {
|
||||
fn clone(&self) -> Self {
|
||||
// SAFETY: This is a clone of a valid slice.
|
||||
unsafe { Slice::from_boxed_slice_unchecked(self.as_boxed_inner().clone()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for &Slice {
|
||||
fn default() -> Self {
|
||||
// SAFETY: The source slice is empty.
|
||||
unsafe { Slice::from_slice_unchecked(<&set::Slice<Entity>>::default()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Box<Slice> {
|
||||
fn default() -> Self {
|
||||
// SAFETY: The source slice is empty.
|
||||
unsafe { Slice::from_boxed_slice_unchecked(<Box<set::Slice<Entity>>>::default()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Debug> Debug for Slice<V> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Slice")
|
||||
.field(&self.0)
|
||||
.field(&&self.1)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Slice> for Box<Slice> {
|
||||
fn from(value: &Slice) -> Self {
|
||||
// SAFETY: This slice is a copy of a valid slice.
|
||||
unsafe { Slice::from_boxed_slice_unchecked(value.1.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Slice {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.1.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Slice {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Slice {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.1.cmp(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Slice {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.1 == other.1
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Slice {}
|
||||
|
||||
impl Index<(Bound<usize>, Bound<usize>)> for Slice {
|
||||
type Output = Self;
|
||||
fn index(&self, key: (Bound<usize>, Bound<usize>)) -> &Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(self.1.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<Range<usize>> for Slice {
|
||||
type Output = Self;
|
||||
fn index(&self, key: Range<usize>) -> &Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(self.1.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<RangeFrom<usize>> for Slice {
|
||||
type Output = Slice;
|
||||
fn index(&self, key: RangeFrom<usize>) -> &Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(self.1.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<RangeFull> for Slice {
|
||||
type Output = Self;
|
||||
fn index(&self, key: RangeFull) -> &Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(self.1.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<RangeInclusive<usize>> for Slice {
|
||||
type Output = Self;
|
||||
fn index(&self, key: RangeInclusive<usize>) -> &Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(self.1.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<RangeTo<usize>> for Slice {
|
||||
type Output = Self;
|
||||
fn index(&self, key: RangeTo<usize>) -> &Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(self.1.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<RangeToInclusive<usize>> for Slice {
|
||||
type Output = Self;
|
||||
fn index(&self, key: RangeToInclusive<usize>) -> &Self {
|
||||
// SAFETY: This a subslice of a valid slice.
|
||||
unsafe { Self::from_slice_unchecked(self.1.index(key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for Slice {
|
||||
type Output = Entity;
|
||||
fn index(&self, key: usize) -> &Entity {
|
||||
self.1.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.
|
||||
@ -185,6 +558,14 @@ impl<'a> Iter<'a> {
|
||||
pub fn into_inner(self) -> set::Iter<'a, Entity> {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Returns a slice of the remaining entries in the iterator.
|
||||
///
|
||||
/// Equivalent to [`set::Iter::as_slice`].
|
||||
pub fn as_slice(&self) -> &Slice {
|
||||
// SAFETY: The source IndexSet uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.as_slice()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Deref for Iter<'a> {
|
||||
@ -246,6 +627,14 @@ impl IntoIter {
|
||||
pub fn into_inner(self) -> set::IntoIter<Entity> {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Returns a slice of the remaining entries in the iterator.
|
||||
///
|
||||
/// Equivalent to [`set::IntoIter::as_slice`].
|
||||
pub fn as_slice(&self) -> &Slice {
|
||||
// SAFETY: The source IndexSet uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.as_slice()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for IntoIter {
|
||||
@ -310,6 +699,14 @@ impl<'a> Drain<'a> {
|
||||
pub fn into_inner(self) -> set::Drain<'a, Entity> {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Returns a slice of the remaining entries in the iterator.$
|
||||
///
|
||||
/// Equivalent to [`set::Drain::as_slice`].
|
||||
pub fn as_slice(&self) -> &Slice {
|
||||
// SAFETY: The source IndexSet uses EntityHash.
|
||||
unsafe { Slice::from_slice_unchecked(self.0.as_slice()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Deref for Drain<'a> {
|
||||
|
Loading…
Reference in New Issue
Block a user