use crate::{
AsMutSlice, AsSlice, Iter, IterMut, SliceMut, SliceRef, SoaClone, SoaDeref, SoaRaw, Soars, Vec,
chunks_exact::ChunksExact, index::SoaIndex, iter_raw::IterRaw,
};
use core::{
cmp::Ordering,
fmt::{self, Debug, Formatter},
hash::{Hash, Hasher},
marker::PhantomData,
ops::{ControlFlow, Deref, DerefMut},
};
pub struct Slice<T: Soars, D: ?Sized = [()]> {
pub(crate) raw: T::Raw,
pub(crate) dst: D,
}
unsafe impl<T: Soars, D: ?Sized> Sync for Slice<T, D> where T: Sync {}
unsafe impl<T: Soars, D: ?Sized> Send for Slice<T, D> where T: Send {}
mod send_sync_fail {}
impl<T> Slice<T, ()>
where
T: Soars,
{
pub(crate) fn empty() -> Self {
Self::with_raw(<T::Raw as SoaRaw>::dangling())
}
#[doc(hidden)]
pub const fn with_raw(raw: T::Raw) -> Self {
Self { raw, dst: () }
}
pub(crate) const unsafe fn as_unsized_mut<'a>(&mut self, len: usize) -> &'a mut Slice<T> {
let ptr = core::ptr::slice_from_raw_parts_mut(self, len) as *mut Slice<T>;
unsafe { &mut *ptr }
}
pub(crate) const unsafe fn as_unsized<'a>(&self, len: usize) -> &'a Slice<T> {
let ptr = core::ptr::slice_from_raw_parts(self, len) as *const Slice<T>;
unsafe { &*ptr }
}
}
impl<T, D> Slice<T, D>
where
T: Soars,
D: ?Sized,
{
#[doc(hidden)]
#[inline]
pub const fn raw(&self) -> T::Raw {
self.raw
}
}
impl<T> Slice<T>
where
T: Soars,
{
pub const fn len(&self) -> usize {
self.dst.len()
}
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
pub const fn iter(&self) -> Iter<'_, T> {
Iter {
iter_raw: IterRaw {
slice: unsafe { self.as_sized() },
len: self.len(),
adapter: PhantomData,
},
_marker: PhantomData,
}
}
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
IterMut {
iter_raw: IterRaw {
slice: unsafe { self.as_sized() },
len: self.len(),
adapter: PhantomData,
},
_marker: PhantomData,
}
}
#[inline]
pub fn get<I>(&self, index: I) -> Option<I::Output<'_>>
where
I: SoaIndex<T>,
{
index.get(self)
}
pub fn get_mut<I>(&mut self, index: I) -> Option<I::OutputMut<'_>>
where
I: SoaIndex<T>,
{
index.get_mut(self)
}
pub fn idx<I>(&self, index: I) -> I::Output<'_>
where
I: SoaIndex<T>,
{
self.get(index).expect("index out of bounds")
}
pub fn idx_mut<I>(&mut self, index: I) -> I::OutputMut<'_>
where
I: SoaIndex<T>,
{
self.get_mut(index).expect("index out of bounds")
}
#[must_use]
pub fn split_at(&self, mid: usize) -> (SliceRef<'_, T>, SliceRef<'_, T>) {
match self.split_at_checked(mid) {
Some(pair) => pair,
None => panic!("mid > len"),
}
}
#[must_use]
pub fn split_at_mut(&mut self, mid: usize) -> (SliceMut<'_, T>, SliceMut<'_, T>) {
match self.split_at_mut_checked(mid) {
Some(pair) => pair,
None => panic!("mid > len"),
}
}
#[must_use]
pub fn split_at_checked(&self, mid: usize) -> Option<(SliceRef<'_, T>, SliceRef<'_, T>)> {
(mid <= self.len()).then(|| unsafe { self.split_at_unchecked(mid) })
}
#[must_use]
pub fn split_at_mut_checked(
&mut self,
mid: usize,
) -> Option<(SliceMut<'_, T>, SliceMut<'_, T>)> {
(mid <= self.len()).then(|| unsafe { self.split_at_mut_unchecked(mid) })
}
#[must_use]
pub unsafe fn split_at_unchecked(&self, mid: usize) -> (SliceRef<'_, T>, SliceRef<'_, T>) {
let (l, r, r_len) = self.split_at_parts(mid);
let l = unsafe { SliceRef::from_slice(l, mid) };
let r = unsafe { SliceRef::from_slice(r, r_len) };
(l, r)
}
#[must_use]
pub unsafe fn split_at_mut_unchecked(
&mut self,
mid: usize,
) -> (SliceMut<'_, T>, SliceMut<'_, T>) {
let (l, r, r_len) = self.split_at_parts(mid);
let l = unsafe { SliceMut::from_slice(l, mid) };
let r = unsafe { SliceMut::from_slice(r, r_len) };
(l, r)
}
fn split_at_parts(&self, mid: usize) -> (Slice<T, ()>, Slice<T, ()>, usize) {
(
unsafe { self.as_sized() },
Slice::with_raw(unsafe { self.raw.offset(mid) }),
self.len() - mid,
)
}
pub fn swap(&mut self, a: usize, b: usize) {
if a >= self.len() || b >= self.len() {
panic!("index out of bounds");
}
unsafe {
let a = self.raw().offset(a);
let b = self.raw().offset(b);
let tmp = a.get();
b.copy_to(a, 1);
b.set(tmp);
}
}
pub fn first(&self) -> Option<T::Ref<'_>> {
self.get(0)
}
pub fn first_mut(&mut self) -> Option<T::RefMut<'_>> {
self.get_mut(0)
}
pub fn last(&self) -> Option<T::Ref<'_>> {
self.get(self.len().saturating_sub(1))
}
pub fn last_mut(&mut self) -> Option<T::RefMut<'_>> {
self.get_mut(self.len().saturating_sub(1))
}
pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> {
if chunk_size == 0 {
panic!("chunk size must be nonzero")
}
ChunksExact::new(self, chunk_size)
}
pub fn slices(&self) -> T::Slices<'_> {
unsafe { self.raw.slices(self.len()) }
}
pub fn slices_mut(&mut self) -> T::SlicesMut<'_> {
unsafe { self.raw.slices_mut(self.len()) }
}
pub(crate) const unsafe fn as_sized(&self) -> Slice<T, ()> {
let ptr = core::ptr::from_ref(self).cast();
unsafe { *ptr }
}
}
impl<T> Clone for Slice<T, ()>
where
T: Soars,
{
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for Slice<T, ()> where T: Soars {}
impl<'a, T> IntoIterator for &'a Slice<T>
where
T: Soars,
{
type Item = T::Ref<'a>;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T> IntoIterator for &'a mut Slice<T>
where
T: Soars,
{
type Item = T::RefMut<'a>;
type IntoIter = IterMut<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<T, R> PartialEq<R> for Slice<T>
where
T: Soars,
R: AsSlice<Item = T> + ?Sized,
for<'a> T::Ref<'a>: PartialEq,
{
fn eq(&self, other: &R) -> bool {
let other = other.as_slice();
self.len() == other.len() && self.iter().zip(other.iter()).all(|(me, them)| me == them)
}
}
impl<T> Eq for Slice<T>
where
T: Soars,
for<'a> T::Ref<'a>: Eq,
{
}
impl<T> Debug for Slice<T>
where
T: Soars,
for<'a> T::Ref<'a>: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let mut list = f.debug_list();
self.iter().for_each(|item| {
list.entry(&item);
});
list.finish()
}
}
impl<T> PartialOrd for Slice<T>
where
T: Soars,
for<'a> T::Ref<'a>: PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match self
.iter()
.zip(other.iter())
.try_fold(Ordering::Equal, |_, (a, b)| match a.partial_cmp(&b) {
ord @ (None | Some(Ordering::Less | Ordering::Greater)) => ControlFlow::Break(ord),
Some(Ordering::Equal) => ControlFlow::Continue(self.len().cmp(&other.len())),
}) {
ControlFlow::Continue(ord) => Some(ord),
ControlFlow::Break(ord) => ord,
}
}
}
impl<T> Ord for Slice<T>
where
T: Soars,
for<'a> T::Ref<'a>: Ord,
{
fn cmp(&self, other: &Self) -> Ordering {
match self
.iter()
.zip(other.iter())
.try_fold(Ordering::Equal, |_, (a, b)| match a.cmp(&b) {
ord @ (Ordering::Greater | Ordering::Less) => ControlFlow::Break(ord),
Ordering::Equal => ControlFlow::Continue(self.len().cmp(&other.len())),
}) {
ControlFlow::Continue(ord) | ControlFlow::Break(ord) => ord,
}
}
}
impl<T> Hash for Slice<T>
where
T: Soars,
for<'a> T::Ref<'a>: Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) {
self.len().hash(state);
for item in self {
item.hash(state);
}
}
}
impl<T> Deref for Slice<T>
where
T: Soars,
{
type Target = T::Deref;
fn deref(&self) -> &Self::Target {
<T::Deref as SoaDeref>::from_slice(self)
}
}
impl<T> DerefMut for Slice<T>
where
T: Soars,
{
fn deref_mut(&mut self) -> &mut Self::Target {
<T::Deref as SoaDeref>::from_slice_mut(self)
}
}
impl<T> AsRef<Slice<T>> for Slice<T>
where
T: Soars,
{
fn as_ref(&self) -> &Self {
self
}
}
impl<T> AsMut<Slice<T>> for Slice<T>
where
T: Soars,
{
fn as_mut(&mut self) -> &mut Self {
self
}
}
impl<T> From<&Slice<T>> for Vec<T>
where
T: SoaClone,
{
fn from(value: &Slice<T>) -> Self {
value.iter().map(SoaClone::soa_clone).collect()
}
}
impl<T> From<&mut Slice<T>> for Vec<T>
where
T: SoaClone,
{
fn from(value: &mut Slice<T>) -> Self {
value.as_ref().into()
}
}
impl<T> AsSlice for Slice<T>
where
T: Soars,
{
type Item = T;
fn as_slice(&self) -> SliceRef<'_, Self::Item> {
unsafe { SliceRef::from_slice(self.as_sized(), self.len()) }
}
}
impl<T> AsMutSlice for Slice<T>
where
T: Soars,
{
fn as_mut_slice(&mut self) -> SliceMut<'_, Self::Item> {
unsafe { SliceMut::from_slice(self.as_sized(), self.len()) }
}
}