diff --git a/crates/bevy_ecs/src/entity/mod.rs b/crates/bevy_ecs/src/entity/mod.rs index 853cb7e4818dc..5f701525d6472 100644 --- a/crates/bevy_ecs/src/entity/mod.rs +++ b/crates/bevy_ecs/src/entity/mod.rs @@ -70,6 +70,10 @@ mod unique_slice; pub use unique_slice::*; +mod unique_array; + +pub use unique_array::UniqueEntityArray; + use crate::{ archetype::{ArchetypeId, ArchetypeRow}, change_detection::MaybeLocation, diff --git a/crates/bevy_ecs/src/entity/unique_array.rs b/crates/bevy_ecs/src/entity/unique_array.rs new file mode 100644 index 0000000000000..f24cf07afb393 --- /dev/null +++ b/crates/bevy_ecs/src/entity/unique_array.rs @@ -0,0 +1,543 @@ +use core::{ + array, + borrow::{Borrow, BorrowMut}, + fmt::Debug, + ops::{ + Bound, Deref, DerefMut, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, + RangeTo, RangeToInclusive, + }, + ptr, +}; + +use alloc::{ + boxed::Box, + collections::{BTreeSet, BinaryHeap, LinkedList, VecDeque}, + rc::Rc, + sync::Arc, + vec::Vec, +}; + +use super::{unique_slice, TrustedEntityBorrow, UniqueEntityIter, UniqueEntitySlice}; + +/// An array that contains only unique entities. +/// +/// It can be obtained through certain methods on [`UniqueEntitySlice`], +/// and some [`TryFrom`] implementations. +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct UniqueEntityArray([T; N]); + +impl UniqueEntityArray { + /// Constructs a `UniqueEntityArray` from a [`[T; N]`] unsafely. + /// + /// # Safety + /// + /// `array` must contain only unique elements. + pub const unsafe fn from_array_unchecked(array: [T; N]) -> Self { + Self(array) + } + + /// Constructs a `&UniqueEntityArray` from a [`&[T; N]`] unsafely. + /// + /// # Safety + /// + /// `array` must contain only unique elements. + pub const unsafe fn from_array_ref_unchecked(array: &[T; N]) -> &Self { + // SAFETY: UniqueEntityArray is a transparent wrapper around [T; N]. + unsafe { &*(ptr::from_ref(array).cast()) } + } + + /// Constructs a `Box` from a [`Box<[T; N]>`] unsafely. + /// + /// # Safety + /// + /// `array` must contain only unique elements. + pub unsafe fn from_boxed_array_unchecked(array: Box<[T; N]>) -> Box { + // SAFETY: UniqueEntityArray is a transparent wrapper around [T; N]. + unsafe { Box::from_raw(Box::into_raw(array).cast()) } + } + + /// Casts `self` into the inner array. + pub fn into_boxed_inner(self: Box) -> Box<[T; N]> { + // SAFETY: UniqueEntityArray is a transparent wrapper around [T; N]. + unsafe { Box::from_raw(Box::into_raw(self).cast()) } + } + + /// Constructs a `Arc` from a [`Arc<[T; N]>`] unsafely. + /// + /// # Safety + /// + /// `slice` must contain only unique elements. + pub unsafe fn from_arc_array_unchecked(slice: Arc<[T; N]>) -> Arc { + // SAFETY: UniqueEntityArray is a transparent wrapper around [T; N]. + unsafe { Arc::from_raw(Arc::into_raw(slice).cast()) } + } + + /// Casts `self` to the inner array. + pub fn into_arc_inner(self: Arc) -> Arc<[T; N]> { + // SAFETY: UniqueEntityArray is a transparent wrapper around [T; N]. + unsafe { Arc::from_raw(Arc::into_raw(self).cast()) } + } + + // Constructs a `Rc` from a [`Rc<[T; N]>`] unsafely. + /// + /// # Safety + /// + /// `slice` must contain only unique elements. + pub unsafe fn from_rc_array_unchecked(slice: Rc<[T; N]>) -> Rc { + // SAFETY: UniqueEntityArray is a transparent wrapper around [T; N]. + unsafe { Rc::from_raw(Rc::into_raw(slice).cast()) } + } + + /// Casts `self` to the inner array. + pub fn into_rc_inner(self: Rc) -> Rc<[T; N]> { + // SAFETY: UniqueEntityArray is a transparent wrapper around [T; N]. + unsafe { Rc::from_raw(Rc::into_raw(self).cast()) } + } + + /// Return the inner array. + pub fn into_inner(self) -> [T; N] { + self.0 + } + + /// Returns a reference to the inner array. + pub fn as_inner(&self) -> &[T; N] { + &self.0 + } + + /// Returns a slice containing the entire array. Equivalent to `&s[..]`. + pub const fn as_slice(&self) -> &UniqueEntitySlice { + // SAFETY: All elements in the original array are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked(self.0.as_slice()) } + } + + /// Returns a mutable slice containing the entire array. Equivalent to + /// `&mut s[..]`. + pub fn as_mut_slice(&mut self) -> &mut UniqueEntitySlice { + // SAFETY: All elements in the original array are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked_mut(self.0.as_mut_slice()) } + } + + /// Borrows each element and returns an array of references with the same + /// size as `self`. + /// + /// Equivalent to [`[T; N]::as_ref`](array::each_ref). + pub fn each_ref(&self) -> UniqueEntityArray<&T, N> { + UniqueEntityArray(self.0.each_ref()) + } +} + +impl Deref for UniqueEntityArray { + type Target = UniqueEntitySlice; + + fn deref(&self) -> &Self::Target { + // SAFETY: All elements in the original array are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked(&self.0) } + } +} + +impl DerefMut for UniqueEntityArray { + fn deref_mut(&mut self) -> &mut Self::Target { + // SAFETY: All elements in the original array are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked_mut(&mut self.0) } + } +} +impl Default for UniqueEntityArray { + fn default() -> Self { + Self(Default::default()) + } +} + +impl<'a, T: TrustedEntityBorrow, const N: usize> IntoIterator for &'a UniqueEntityArray { + type Item = &'a T; + + type IntoIter = unique_slice::Iter<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + // SAFETY: All elements in the original array are unique. + unsafe { UniqueEntityIter::from_iterator_unchecked(self.0.iter()) } + } +} + +impl IntoIterator for UniqueEntityArray { + type Item = T; + + type IntoIter = IntoIter; + + fn into_iter(self) -> Self::IntoIter { + // SAFETY: All elements in the original array are unique. + unsafe { UniqueEntityIter::from_iterator_unchecked(self.0.into_iter()) } + } +} + +impl AsRef> + for UniqueEntityArray +{ + fn as_ref(&self) -> &UniqueEntitySlice { + self + } +} + +impl AsMut> + for UniqueEntityArray +{ + fn as_mut(&mut self) -> &mut UniqueEntitySlice { + self + } +} + +impl Borrow> + for UniqueEntityArray +{ + fn borrow(&self) -> &UniqueEntitySlice { + self + } +} + +impl BorrowMut> + for UniqueEntityArray +{ + fn borrow_mut(&mut self) -> &mut UniqueEntitySlice { + self + } +} + +impl Index<(Bound, Bound)> + for UniqueEntityArray +{ + type Output = UniqueEntitySlice; + fn index(&self, key: (Bound, Bound)) -> &Self::Output { + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked(self.0.index(key)) } + } +} + +impl Index> for UniqueEntityArray { + type Output = UniqueEntitySlice; + fn index(&self, key: Range) -> &Self::Output { + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked(self.0.index(key)) } + } +} + +impl Index> for UniqueEntityArray { + type Output = UniqueEntitySlice; + fn index(&self, key: RangeFrom) -> &Self::Output { + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked(self.0.index(key)) } + } +} + +impl Index for UniqueEntityArray { + type Output = UniqueEntitySlice; + fn index(&self, key: RangeFull) -> &Self::Output { + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked(self.0.index(key)) } + } +} + +impl Index> + for UniqueEntityArray +{ + type Output = UniqueEntitySlice; + fn index(&self, key: RangeInclusive) -> &Self::Output { + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked(self.0.index(key)) } + } +} + +impl Index> for UniqueEntityArray { + type Output = UniqueEntitySlice; + fn index(&self, key: RangeTo) -> &Self::Output { + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked(self.0.index(key)) } + } +} + +impl Index> + for UniqueEntityArray +{ + type Output = UniqueEntitySlice; + fn index(&self, key: RangeToInclusive) -> &Self::Output { + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked(self.0.index(key)) } + } +} + +impl Index for UniqueEntityArray { + type Output = T; + fn index(&self, key: usize) -> &T { + self.0.index(key) + } +} + +impl IndexMut<(Bound, Bound)> + for UniqueEntityArray +{ + fn index_mut(&mut self, key: (Bound, Bound)) -> &mut Self::Output { + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked_mut(self.0.index_mut(key)) } + } +} + +impl IndexMut> for UniqueEntityArray { + fn index_mut(&mut self, key: Range) -> &mut Self::Output { + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked_mut(self.0.index_mut(key)) } + } +} + +impl IndexMut> + for UniqueEntityArray +{ + fn index_mut(&mut self, key: RangeFrom) -> &mut Self::Output { + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked_mut(self.0.index_mut(key)) } + } +} + +impl IndexMut for UniqueEntityArray { + fn index_mut(&mut self, key: RangeFull) -> &mut Self::Output { + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked_mut(self.0.index_mut(key)) } + } +} + +impl IndexMut> + for UniqueEntityArray +{ + fn index_mut(&mut self, key: RangeInclusive) -> &mut Self::Output { + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked_mut(self.0.index_mut(key)) } + } +} + +impl IndexMut> for UniqueEntityArray { + fn index_mut(&mut self, key: RangeTo) -> &mut Self::Output { + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked_mut(self.0.index_mut(key)) } + } +} + +impl IndexMut> + for UniqueEntityArray +{ + fn index_mut(&mut self, key: RangeToInclusive) -> &mut Self::Output { + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked_mut(self.0.index_mut(key)) } + } +} + +impl From<&[T; 1]> for UniqueEntityArray { + fn from(value: &[T; 1]) -> Self { + Self(value.clone()) + } +} + +impl From<&[T; 0]> for UniqueEntityArray { + fn from(value: &[T; 0]) -> Self { + Self(value.clone()) + } +} + +impl From<&mut [T; 1]> for UniqueEntityArray { + fn from(value: &mut [T; 1]) -> Self { + Self(value.clone()) + } +} + +impl From<&mut [T; 0]> for UniqueEntityArray { + fn from(value: &mut [T; 0]) -> Self { + Self(value.clone()) + } +} + +impl From<[T; 1]> for UniqueEntityArray { + fn from(value: [T; 1]) -> Self { + Self(value) + } +} + +impl From<[T; 0]> for UniqueEntityArray { + fn from(value: [T; 0]) -> Self { + Self(value) + } +} + +impl From> for (T,) { + fn from(array: UniqueEntityArray) -> Self { + Self::from(array.into_inner()) + } +} + +impl From> for (T, T) { + fn from(array: UniqueEntityArray) -> Self { + Self::from(array.into_inner()) + } +} + +impl From> for (T, T, T) { + fn from(array: UniqueEntityArray) -> Self { + Self::from(array.into_inner()) + } +} + +impl From> for (T, T, T, T) { + fn from(array: UniqueEntityArray) -> Self { + Self::from(array.into_inner()) + } +} + +impl From> for (T, T, T, T, T) { + fn from(array: UniqueEntityArray) -> Self { + Self::from(array.into_inner()) + } +} + +impl From> for (T, T, T, T, T, T) { + fn from(array: UniqueEntityArray) -> Self { + Self::from(array.into_inner()) + } +} + +impl From> for (T, T, T, T, T, T, T) { + fn from(array: UniqueEntityArray) -> Self { + Self::from(array.into_inner()) + } +} + +impl From> for (T, T, T, T, T, T, T, T) { + fn from(array: UniqueEntityArray) -> Self { + Self::from(array.into_inner()) + } +} + +impl From> for (T, T, T, T, T, T, T, T, T) { + fn from(array: UniqueEntityArray) -> Self { + Self::from(array.into_inner()) + } +} + +impl From> for (T, T, T, T, T, T, T, T, T, T) { + fn from(array: UniqueEntityArray) -> Self { + Self::from(array.into_inner()) + } +} + +impl From> for (T, T, T, T, T, T, T, T, T, T, T) { + fn from(array: UniqueEntityArray) -> Self { + Self::from(array.into_inner()) + } +} + +impl From> + for (T, T, T, T, T, T, T, T, T, T, T, T) +{ + fn from(array: UniqueEntityArray) -> Self { + Self::from(array.into_inner()) + } +} + +impl From> for BTreeSet { + fn from(value: UniqueEntityArray) -> Self { + BTreeSet::from(value.0) + } +} + +impl From> for BinaryHeap { + fn from(value: UniqueEntityArray) -> Self { + BinaryHeap::from(value.0) + } +} + +impl From> for LinkedList { + fn from(value: UniqueEntityArray) -> Self { + LinkedList::from(value.0) + } +} + +impl From> for Vec { + fn from(value: UniqueEntityArray) -> Self { + Vec::from(value.0) + } +} + +impl From> for VecDeque { + fn from(value: UniqueEntityArray) -> Self { + VecDeque::from(value.0) + } +} + +impl, U: TrustedEntityBorrow, const N: usize> + PartialEq<&UniqueEntitySlice> for UniqueEntityArray +{ + fn eq(&self, other: &&UniqueEntitySlice) -> bool { + self.0.eq(&other.as_inner()) + } +} + +impl, U: TrustedEntityBorrow, const N: usize> + PartialEq> for UniqueEntityArray +{ + fn eq(&self, other: &UniqueEntitySlice) -> bool { + self.0.eq(other.as_inner()) + } +} + +impl, U: TrustedEntityBorrow, const N: usize> PartialEq<&UniqueEntityArray> + for Vec +{ + fn eq(&self, other: &&UniqueEntityArray) -> bool { + self.eq(&other.0) + } +} +impl, U: TrustedEntityBorrow, const N: usize> PartialEq<&UniqueEntityArray> + for VecDeque +{ + fn eq(&self, other: &&UniqueEntityArray) -> bool { + self.eq(&other.0) + } +} + +impl, U: TrustedEntityBorrow, const N: usize> + PartialEq<&mut UniqueEntityArray> for VecDeque +{ + fn eq(&self, other: &&mut UniqueEntityArray) -> bool { + self.eq(&other.0) + } +} + +impl, U: TrustedEntityBorrow, const N: usize> PartialEq> + for Vec +{ + fn eq(&self, other: &UniqueEntityArray) -> bool { + self.eq(&other.0) + } +} +impl, U: TrustedEntityBorrow, const N: usize> PartialEq> + for VecDeque +{ + fn eq(&self, other: &UniqueEntityArray) -> bool { + self.eq(&other.0) + } +} + +pub type IntoIter = UniqueEntityIter>; + +impl UniqueEntityIter> { + /// Returns an immutable slice of all elements that have not been yielded + /// yet. + /// + /// Equivalent to [`array::IntoIter::as_slice`]. + pub fn as_slice(&self) -> &UniqueEntitySlice { + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked(self.as_inner().as_slice()) } + } + + /// Returns a mutable slice of all elements that have not been yielded yet. + /// + /// Equivalent to [`array::IntoIter::as_mut_slice`]. + pub fn as_mut_slice(&mut self) -> &mut UniqueEntitySlice { + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntitySlice::from_slice_unchecked_mut(self.as_mut_inner().as_mut_slice()) } + } +} diff --git a/crates/bevy_ecs/src/entity/unique_slice.rs b/crates/bevy_ecs/src/entity/unique_slice.rs index f3a6f66de7e87..91060e763835a 100644 --- a/crates/bevy_ecs/src/entity/unique_slice.rs +++ b/crates/bevy_ecs/src/entity/unique_slice.rs @@ -1,4 +1,5 @@ use core::{ + array::TryFromSliceError, borrow::Borrow, cmp::Ordering, fmt::Debug, @@ -22,7 +23,7 @@ use alloc::{ use super::{ unique_vec, EntitySet, EntitySetIterator, FromEntitySetIterator, TrustedEntityBorrow, - UniqueEntityIter, UniqueEntityVec, + UniqueEntityArray, UniqueEntityIter, UniqueEntityVec, }; /// A slice that contains only unique entities. @@ -128,6 +129,64 @@ impl UniqueEntitySlice { Some((last, unsafe { Self::from_slice_unchecked(rest) })) } + /// Returns an array reference to the first `N` items in the slice. + /// + /// Equivalent to [`[T]::first_chunk`](slice::first_chunk). + pub const fn first_chunk(&self) -> Option<&UniqueEntityArray> { + let Some(chunk) = self.0.first_chunk() else { + return None; + }; + // SAFETY: All elements in the original slice are unique. + Some(unsafe { UniqueEntityArray::from_array_ref_unchecked(chunk) }) + } + + /// Returns an array reference to the first `N` items in the slice and the remaining slice. + /// + /// Equivalent to [`[T]::split_first_chunk`](slice::split_first_chunk). + pub const fn split_first_chunk( + &self, + ) -> Option<(&UniqueEntityArray, &UniqueEntitySlice)> { + let Some((chunk, rest)) = self.0.split_first_chunk() else { + return None; + }; + // SAFETY: All elements in the original slice are unique. + unsafe { + Some(( + UniqueEntityArray::from_array_ref_unchecked(chunk), + Self::from_slice_unchecked(rest), + )) + } + } + + /// Returns an array reference to the last `N` items in the slice and the remaining slice. + /// + /// Equivalent to [`[T]::split_last_chunk`](slice::split_last_chunk). + pub const fn split_last_chunk( + &self, + ) -> Option<(&UniqueEntitySlice, &UniqueEntityArray)> { + let Some((rest, chunk)) = self.0.split_last_chunk() else { + return None; + }; + // SAFETY: All elements in the original slice are unique. + unsafe { + Some(( + Self::from_slice_unchecked(rest), + UniqueEntityArray::from_array_ref_unchecked(chunk), + )) + } + } + + /// Returns an array reference to the last `N` items in the slice. + /// + /// Equivalent to [`[T]::last_chunk`](slice::last_chunk). + pub const fn last_chunk(&self) -> Option<&UniqueEntityArray> { + let Some(chunk) = self.0.last_chunk() else { + return None; + }; + // SAFETY: All elements in the original slice are unique. + Some(unsafe { UniqueEntityArray::from_array_ref_unchecked(chunk) }) + } + /// Returns a reference to a subslice. /// /// Equivalent to the range functionality of [`[T]::get`]. @@ -949,6 +1008,15 @@ impl<'a, T: TrustedEntityBorrow + Clone> From<&'a UniqueEntitySlice> } } +impl From> + for Box> +{ + fn from(value: UniqueEntityArray) -> Self { + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntitySlice::from_boxed_slice_unchecked(Box::new(value.into_inner())) } + } +} + impl<'a, T: TrustedEntityBorrow + Clone> From>> for Box> { @@ -1134,6 +1202,30 @@ impl, U, const N: usize> PartialEq<[U; N]> } } +impl, U: TrustedEntityBorrow, const N: usize> + PartialEq> for &UniqueEntitySlice +{ + fn eq(&self, other: &UniqueEntityArray) -> bool { + self.0.eq(&other.0) + } +} + +impl, U: TrustedEntityBorrow, const N: usize> + PartialEq> for &mut UniqueEntitySlice +{ + fn eq(&self, other: &UniqueEntityArray) -> bool { + self.0.eq(&other.0) + } +} + +impl, U: TrustedEntityBorrow, const N: usize> + PartialEq> for UniqueEntitySlice +{ + fn eq(&self, other: &UniqueEntityArray) -> bool { + self.0.eq(&other.0) + } +} + impl, U> PartialEq> for &UniqueEntitySlice { fn eq(&self, other: &Vec) -> bool { self.0.eq(other) @@ -1161,6 +1253,38 @@ impl ToOwned for UniqueEntitySlice { } } +impl<'a, T: TrustedEntityBorrow + Copy, const N: usize> TryFrom<&'a UniqueEntitySlice> + for &'a UniqueEntityArray +{ + type Error = TryFromSliceError; + + fn try_from(value: &'a UniqueEntitySlice) -> Result { + <&[T; N]>::try_from(&value.0).map(|array| + // SAFETY: All elements in the original slice are unique. + unsafe { UniqueEntityArray::from_array_ref_unchecked(array) }) + } +} + +impl TryFrom<&UniqueEntitySlice> + for UniqueEntityArray +{ + type Error = TryFromSliceError; + + fn try_from(value: &UniqueEntitySlice) -> Result { + <&Self>::try_from(value).copied() + } +} + +impl TryFrom<&mut UniqueEntitySlice> + for UniqueEntityArray +{ + type Error = TryFromSliceError; + + fn try_from(value: &mut UniqueEntitySlice) -> Result { + ::try_from(&*value) + } +} + impl Index<(Bound, Bound)> for UniqueEntitySlice { type Output = Self; fn index(&self, key: (Bound, Bound)) -> &Self { diff --git a/crates/bevy_ecs/src/entity/unique_vec.rs b/crates/bevy_ecs/src/entity/unique_vec.rs index 9ea1f9c7a6b39..101293129d6a3 100644 --- a/crates/bevy_ecs/src/entity/unique_vec.rs +++ b/crates/bevy_ecs/src/entity/unique_vec.rs @@ -17,8 +17,8 @@ use alloc::{ }; use super::{ - unique_slice, EntitySet, FromEntitySetIterator, TrustedEntityBorrow, UniqueEntityIter, - UniqueEntitySlice, + unique_slice, EntitySet, FromEntitySetIterator, TrustedEntityBorrow, UniqueEntityArray, + UniqueEntityIter, UniqueEntitySlice, }; /// A `Vec` that contains only unique entities. @@ -550,6 +550,14 @@ impl, U, const N: usize> PartialEq<&[U; N] } } +impl, U: TrustedEntityBorrow, const N: usize> + PartialEq<&UniqueEntityArray> for UniqueEntityVec +{ + fn eq(&self, other: &&UniqueEntityArray) -> bool { + self.0.eq(&other.as_inner()) + } +} + impl, U, const N: usize> PartialEq<&mut [U; N]> for UniqueEntityVec { @@ -558,6 +566,14 @@ impl, U, const N: usize> PartialEq<&mut [U } } +impl, U: TrustedEntityBorrow, const N: usize> + PartialEq<&mut UniqueEntityArray> for UniqueEntityVec +{ + fn eq(&self, other: &&mut UniqueEntityArray) -> bool { + self.0.eq(other.as_inner()) + } +} + impl, U> PartialEq<[U]> for UniqueEntityVec { fn eq(&self, other: &[U]) -> bool { self.0.eq(other) @@ -580,6 +596,14 @@ impl, U, const N: usize> PartialEq<[U; N]> } } +impl, U: TrustedEntityBorrow, const N: usize> + PartialEq> for UniqueEntityVec +{ + fn eq(&self, other: &UniqueEntityArray) -> bool { + self.0.eq(other.as_inner()) + } +} + impl, U: TrustedEntityBorrow> PartialEq> for Vec { fn eq(&self, other: &UniqueEntityVec) -> bool { self.eq(&other.0) @@ -683,6 +707,28 @@ impl From<[T; 0]> for UniqueEntityVec { } } +impl From<&UniqueEntityArray> + for UniqueEntityVec +{ + fn from(value: &UniqueEntityArray) -> Self { + Self(Vec::from(value.as_inner().clone())) + } +} + +impl From<&mut UniqueEntityArray> + for UniqueEntityVec +{ + fn from(value: &mut UniqueEntityArray) -> Self { + Self(Vec::from(value.as_inner().clone())) + } +} + +impl From> for UniqueEntityVec { + fn from(value: UniqueEntityArray) -> Self { + Self(Vec::from(value.into_inner())) + } +} + impl From> for Vec { fn from(value: UniqueEntityVec) -> Self { value.0 @@ -755,6 +801,20 @@ impl TryFrom> for Box } } +impl TryFrom> + for Box> +{ + type Error = UniqueEntityVec; + + fn try_from(value: UniqueEntityVec) -> Result { + Box::try_from(value.0) + .map(|v| + // SAFETY: All elements in the original Vec are unique. + unsafe { UniqueEntityArray::from_boxed_array_unchecked(v) }) + .map_err(UniqueEntityVec) + } +} + impl TryFrom> for [T; N] { type Error = UniqueEntityVec; @@ -763,6 +823,20 @@ impl TryFrom> for [T; } } +impl TryFrom> + for UniqueEntityArray +{ + type Error = UniqueEntityVec; + + fn try_from(value: UniqueEntityVec) -> Result { + <[T; N] as TryFrom>>::try_from(value.0) + .map(|v| + // SAFETY: All elements in the original Vec are unique. + unsafe { UniqueEntityArray::from_array_unchecked(v) }) + .map_err(UniqueEntityVec) + } +} + impl From> for UniqueEntityVec { fn from(value: BTreeSet) -> Self { Self(value.into_iter().collect::>())