#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
#[allow(unused_imports)]
use alloc::{vec::Vec,string::String};
pub use layout_internal::SOA;
#[doc(hidden)]
pub use permutation::permutation::*;
pub trait SOA {
type Type;
}
pub trait SoAIter<'a> {
type Ref;
type RefMut;
type Iter: 'a + Iterator<Item=Self::Ref>;
type IterMut: 'a + Iterator<Item=Self::RefMut>;
}
mod private_soa_indexes {
use ::core::ops;
pub trait Sealed {}
impl Sealed for usize {} impl Sealed for ops::Range<usize> {} impl Sealed for ops::RangeTo<usize> {} impl Sealed for ops::RangeFrom<usize> {} impl Sealed for ops::RangeFull {} impl Sealed for ops::RangeInclusive<usize> {} impl Sealed for ops::RangeToInclusive<usize> {} }
pub trait SoAIndex<T>: private_soa_indexes::Sealed {
type RefOutput;
fn get(self, soa: T) -> Option<Self::RefOutput>;
unsafe fn get_unchecked(self, soa: T) -> Self::RefOutput;
fn index(self, soa: T) -> Self::RefOutput;
}
pub trait SoAIndexMut<T>: private_soa_indexes::Sealed {
type MutOutput;
fn get_mut(self, soa: T) -> Option<Self::MutOutput>;
unsafe fn get_unchecked_mut(self, soa: T) -> Self::MutOutput;
fn index_mut(self, soa: T) -> Self::MutOutput;
}
#[macro_export]
macro_rules! soa_zip {
($self: expr, [$($fields: tt)*] $(, $external: expr)* $(,)*) => {{
let this = $self;
$crate::soa_zip_impl!(@munch this, {$($fields)*} -> [] $($external ,)*)
}};
}
pub trait SoAPointers {
type Ptr;
type MutPtr;
}
mod generics {
use super::*;
pub trait SoASlice<T: SOA> {
type Ref<'t> where Self: 't;
type Slice<'t>: SoASlice<T> + IntoSoAIter<'t, T, Ref<'t> = Self::Ref<'t>> where Self: 't;
type Iter<'t>: Iterator<Item=Self::Ref<'t>> where Self: 't;
type Ptr;
fn len(&self) -> usize;
fn is_empty(&self) -> bool;
fn as_slice(&self) -> Self::Slice<'_>;
fn slice<'c, 'a: 'c>(&'c self, index: impl core::ops::RangeBounds<usize>) -> Self::Slice<'c> where Self: 'a;
fn get(&self, index: usize) -> Option<Self::Ref<'_>>;
fn index(&self, index: usize) -> Self::Ref<'_>;
fn iter(&self) -> Self::Iter<'_>;
fn first(&self) -> Option<Self::Ref<'_>> {
self.get(0)
}
fn last(&self) -> Option<Self::Ref<'_>> {
self.get(self.len().saturating_sub(1))
}
fn as_ptr(&self) -> Self::Ptr;
}
pub trait SoASliceMut<T: SOA> {
type Ref<'t> where Self: 't;
type Slice<'t>: SoASlice<T> + IntoSoAIter<'t, T, Ref<'t> = Self::Ref<'t>> where Self: 't;
type Iter<'t>: Iterator<Item=Self::Ref<'t>> where Self: 't;
type Ptr;
type RefMut<'t> where Self: 't;
type SliceMut<'t>: SoASliceMut<T> where Self: 't;
type IterMut<'t>: Iterator<Item=Self::RefMut<'t>> where Self: 't;
type PtrMut;
fn len(&self) -> usize;
fn is_empty(&self) -> bool;
fn as_slice(&self) -> Self::Slice<'_>;
fn slice<'c, 'a: 'c>(&'c self, index: impl core::ops::RangeBounds<usize>) -> Self::Slice<'c> where Self: 'a;
fn get(&self, index: usize) -> Option<Self::Ref<'_>>;
fn index(&self, index: usize) -> Self::Ref<'_>;
fn iter(&self) -> Self::Iter<'_>;
fn first(&self) -> Option<Self::Ref<'_>> {
self.get(0)
}
fn last(&self) -> Option<Self::Ref<'_>> {
self.get(self.len().saturating_sub(1))
}
fn as_ptr(&self) -> Self::Ptr;
fn as_mut_slice<'c: 'b, 'b>(&'c mut self) -> Self::SliceMut<'c> where Self: 'b;
fn slice_mut(&mut self, index: impl core::ops::RangeBounds<usize>) -> Self::SliceMut<'_>;
fn get_mut(&mut self, index: usize) -> Option<Self::RefMut<'_>>;
fn index_mut(&mut self, index: usize) -> Self::RefMut<'_>;
fn iter_mut(&mut self) -> Self::IterMut<'_>;
fn apply_index(&mut self, indices: &[usize]);
fn sort_by<F>(&mut self, mut f: F) where F: FnMut(Self::Ref<'_>, Self::Ref<'_>) -> core::cmp::Ordering {
let mut permutation: Vec<usize> = (0..self.len()).collect();
permutation.sort_by(|j, k| f(self.index(*j), self.index(*k)));
self.apply_index(&permutation);
}
fn sort_by_key<F, K>(&mut self, mut f: F) where
F: FnMut(Self::Ref<'_>) -> K,
K: Ord,
{
let mut permutation: Vec<usize> = (0..self.len()).collect();
permutation.sort_by_key(|j| f(self.index(*j)));
self.apply_index(&permutation);
}
fn first_mut(&mut self) -> Option<Self::RefMut<'_>> {
self.get_mut(0)
}
fn last_mut(&mut self) -> Option<Self::RefMut<'_>> {
self.get_mut(self.len().saturating_sub(1))
}
fn as_mut_ptr(&mut self) -> Self::PtrMut;
}
pub trait SoAVec<T: SOA> {
type Ref<'t> where Self: 't;
type Slice<'t>: SoASlice<T> + IntoSoAIter<'t, T> where Self: 't;
type Iter<'t>: Iterator<Item=Self::Ref<'t>> where Self: 't;
type Ptr;
type RefMut<'t> where Self: 't;
type SliceMut<'t>: SoASliceMut<T> where Self: 't;
type IterMut<'t>: Iterator<Item=Self::RefMut<'t>> where Self: 't;
type PtrMut;
fn len(&self) -> usize;
fn is_empty(&self) -> bool;
fn as_slice<'c, 'a: 'c>(&'c self) -> Self::Slice<'c> where Self: 'a;
fn slice<'c, 'a: 'c>(&'c self, index: impl core::ops::RangeBounds<usize>) -> Self::Slice<'c> where Self: 'a;
fn get(&self, index: usize) -> Option<Self::Ref<'_>>;
fn index(&self, index: usize) -> Self::Ref<'_>;
fn iter(&self) -> Self::Iter<'_>;
fn first(&self) -> Option<Self::Ref<'_>> {
self.get(0)
}
fn last(&self) -> Option<Self::Ref<'_>> {
self.get(self.len().saturating_sub(1))
}
fn as_ptr(&self) -> Self::Ptr;
fn as_mut_slice<'c, 'a: 'c>(&'c mut self) -> Self::SliceMut<'c> where Self: 'a;
fn slice_mut(&mut self, index: impl core::ops::RangeBounds<usize>) -> Self::SliceMut<'_>;
fn get_mut(&mut self, index: usize) -> Option<Self::RefMut<'_>>;
fn index_mut(&mut self, index: usize) -> Self::RefMut<'_>;
fn iter_mut(&mut self) -> Self::IterMut<'_>;
fn apply_index(&mut self, indices: &[usize]);
fn sort_by<F>(&mut self, mut f: F) where F: FnMut(Self::Ref<'_>, Self::Ref<'_>) -> core::cmp::Ordering {
let mut permutation: Vec<usize> = (0..self.len()).collect();
permutation.sort_by(|j, k| f(self.index(*j), self.index(*k)));
self.apply_index(&permutation);
}
fn sort_by_key<F, K>(&mut self, mut f: F) where
F: FnMut(Self::Ref<'_>) -> K,
K: Ord,
{
let mut permutation: Vec<usize> = (0..self.len()).collect();
permutation.sort_by_key(|j| f(self.index(*j)));
self.apply_index(&permutation);
}
fn first_mut(&mut self) -> Option<Self::RefMut<'_>> {
self.get_mut(0)
}
fn last_mut(&mut self) -> Option<Self::RefMut<'_>> {
self.get_mut(self.len().saturating_sub(1))
}
fn as_mut_ptr(&mut self) -> Self::PtrMut;
fn new() -> Self;
fn with_capacity(capacity: usize) -> Self;
fn capacity(&self) -> usize;
fn reserve(&mut self, additional: usize);
fn reserve_exact(&mut self, additional: usize);
fn shrink_to_fit(&mut self);
fn truncate(&mut self, len: usize);
fn push(&mut self, value: T);
fn swap_remove(&mut self, index: usize) -> T;
fn insert(&mut self, index: usize, element: T);
fn replace(&mut self, index: usize, element: T) -> T;
fn remove(&mut self, index: usize) -> T;
fn pop(&mut self) -> Option<T>;
fn append(&mut self, other: &mut Self);
fn clear(&mut self);
fn split_off(&mut self, at: usize) -> Self;
}
pub trait ToSoAVec<T: SOA> {
type SoAVecType: SoAVec<T>;
fn to_vec(&self) -> Self::SoAVecType;
}
pub trait SoAAppendVec<T: SOA>: SoAVec<T> {
fn extend_from_slice(&mut self, other: Self::Slice<'_>);
}
pub trait IntoSoAIter<'a, T: SOA>: SoASlice<T> + IntoIterator<Item=Self::Ref<'a>> + 'a {}
}
pub use generics::*;
#[macro_export]
#[doc(hidden)]
macro_rules! soa_zip_impl {
(@flatten $p:pat => $tup:expr ) => {
|$p| $tup
};
(@flatten $p:pat => ( $($tup:tt)* ) , $_iter:expr $( , $tail:expr )* ) => {
$crate::soa_zip_impl!(@flatten ($p, a) => ( $($tup)*, a ) $( , $tail )*)
};
(@last , $first: expr, $($tail: expr,)*) => {
::core::iter::IntoIterator::into_iter($first)
$(
.zip($tail)
)*
.map(
$crate::soa_zip_impl!(@flatten a => (a) $( , $tail )*)
)
};
(@munch $self: expr, {mut $field: ident} -> [$($output: tt)*] $($ext: expr ,)*) => {
$crate::soa_zip_impl!(@last $($output)*, $self.$field.iter_mut(), $($ext, )*)
};
(@munch $self: expr, {$field: ident} -> [$($output: tt)*] $($ext: expr ,)*) => {
$crate::soa_zip_impl!(@last $($output)*, $self.$field.iter(), $($ext, )*)
};
(@munch $self: expr, {mut $field: ident, $($tail: tt)*} -> [$($output: tt)*] $($ext: expr ,)*) => {
$crate::soa_zip_impl!(@munch $self, {$($tail)*} -> [$($output)*, $self.$field.iter_mut()] $($ext, )*)
};
(@munch $self: expr, {$field: ident, $($tail: tt)*} -> [$($output: tt)*] $($ext: expr ,)*) => {
$crate::soa_zip_impl!(@munch $self, {$($tail)*} -> [$($output)*, $self.$field.iter()] $($ext, )*)
};
}