macro_rules! impl_atom_iterators_recursive {
(impl<S, $($type_vars_decl:tt),*> for $type:ident<S, $($type_vars:tt),*> { $data_field:ident }) => {
impl<'a, S, $($type_vars_decl,)*> AtomIterator<'a> for $type<S, $($type_vars,)*>
where S: AtomIterator<'a>,
{
type Item = S::Item;
type Iter = S::Iter;
fn atom_iter(&'a self) -> Self::Iter {
self.$data_field.atom_iter()
}
}
impl<'a, S, $($type_vars_decl,)*> AtomMutIterator<'a> for $type<S, $($type_vars,)*>
where S: AtomMutIterator<'a>
{
type Item = S::Item;
type Iter = S::Iter;
fn atom_mut_iter(&'a mut self) -> Self::Iter {
self.$data_field.atom_mut_iter()
}
}
}
}
macro_rules! impl_isolate_index_for_static_range {
(impl<$($type_vars:ident),*> for $type:ty) => {
impl_isolate_index_for_static_range! { impl<$($type_vars),*> for $type where }
};
(impl<$($type_vars:ident),*> for $type:ty where $($constraints:tt)*) => {
impl<$($type_vars,)* N: Unsigned> IsolateIndex<$type> for StaticRange<N>
where
std::ops::Range<usize>: IsolateIndex<$type>,
$($constraints)*
{
type Output = <std::ops::Range<usize> as IsolateIndex<$type>>::Output;
#[inline]
unsafe fn isolate_unchecked(self, set: $type) -> Self::Output {
IsolateIndex::isolate_unchecked(self.start..self.start + N::to_usize(), set)
}
#[inline]
fn try_isolate(self, set: $type) -> Option<Self::Output> {
IsolateIndex::try_isolate(self.start..self.start + N::to_usize(), set)
}
}
}
}
mod macros;
mod array;
mod boxed;
mod chunked;
#[cfg(feature = "gpu")]
pub mod gpu;
mod range;
mod select;
mod slice;
#[cfg(feature = "sparse")]
mod sparse;
mod subset;
mod tuple;
mod vec;
mod view;
pub use array::*;
pub use boxed::*;
pub use chunked::*;
#[cfg(feature = "gpu")]
pub use gpu::IntoGpu;
pub use range::*;
pub use select::*;
pub use slice::*;
#[cfg(feature = "sparse")]
pub use sparse::*;
pub use subset::*;
pub use tuple::*;
pub use vec::*;
pub use view::*;
#[cfg(feature = "derive")]
pub use flatk_derive::{Component, U};
pub use typenum::consts;
use typenum::type_operators::PartialDiv;
pub use typenum::Unsigned;
pub trait Set {
type Elem;
type Atom;
fn len(&self) -> usize;
#[inline]
fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl<N: Unsigned> Set for StaticRange<N> {
type Elem = usize;
type Atom = usize;
#[inline]
fn len(&self) -> usize {
N::to_usize()
}
}
impl<S: Set + ?Sized> Set for &S {
type Elem = <S as Set>::Elem;
type Atom = <S as Set>::Elem;
#[inline]
fn len(&self) -> usize {
<S as Set>::len(self)
}
}
impl<S: Set + ?Sized> Set for &mut S {
type Elem = <S as Set>::Elem;
type Atom = <S as Set>::Elem;
#[inline]
fn len(&self) -> usize {
<S as Set>::len(self)
}
}
impl<S: Set + ?Sized> Set for std::cell::Ref<'_, S> {
type Elem = <S as Set>::Elem;
type Atom = <S as Set>::Elem;
#[inline]
fn len(&self) -> usize {
<S as Set>::len(self)
}
}
impl<S: Set + ?Sized> Set for std::cell::RefMut<'_, S> {
type Elem = <S as Set>::Elem;
type Atom = <S as Set>::Elem;
#[inline]
fn len(&self) -> usize {
<S as Set>::len(self)
}
}
pub trait AsFlatSlice<T> {
fn as_flat_slice(&self) -> &[T];
}
pub trait Array<T> {
type Array: Set<Elem = T> + bytemuck::Pod;
fn iter_mut(array: &mut Self::Array) -> std::slice::IterMut<T>;
fn iter(array: &Self::Array) -> std::slice::Iter<T>;
fn as_slice(array: &Self::Array) -> &[T];
}
pub trait DynamicRangeIndexType {}
#[cfg(feature = "sparse")]
impl<S, T, I> DynamicRangeIndexType for Sparse<S, T, I> {}
impl<S, I> DynamicRangeIndexType for Select<S, I> {}
impl<S, I> DynamicRangeIndexType for Subset<S, I> {}
impl<S, I> DynamicRangeIndexType for Chunked<S, I> {}
impl<S> DynamicRangeIndexType for ChunkedN<S> {}
pub trait ValueType {}
#[cfg(feature = "sparse")]
impl<S, T, I> ValueType for Sparse<S, T, I> {}
impl<S, I> ValueType for Select<S, I> {}
impl<S, I> ValueType for Subset<S, I> {}
impl<S, I> ValueType for Chunked<S, I> {}
impl<S, N> ValueType for UniChunked<S, N> {}
impl<S: Viewed + ?Sized> Viewed for &S {}
impl<S: Viewed + ?Sized> Viewed for &mut S {}
#[cfg(feature = "sparse")]
impl<S: Viewed, T: Viewed, I: Viewed> Viewed for Sparse<S, T, I> {}
impl<S: Viewed, I: Viewed> Viewed for Select<S, I> {}
impl<S: Viewed, I: Viewed> Viewed for Subset<S, I> {}
impl<S: Viewed, I: Viewed> Viewed for Chunked<S, I> {}
impl<S: Viewed, N> Viewed for UniChunked<S, N> {}
pub trait StaticallySplittable:
IntoStaticChunkIterator<consts::U2>
+ IntoStaticChunkIterator<consts::U3>
+ IntoStaticChunkIterator<consts::U4>
+ IntoStaticChunkIterator<consts::U5>
+ IntoStaticChunkIterator<consts::U6>
+ IntoStaticChunkIterator<consts::U7>
+ IntoStaticChunkIterator<consts::U8>
+ IntoStaticChunkIterator<consts::U9>
+ IntoStaticChunkIterator<consts::U10>
+ IntoStaticChunkIterator<consts::U11>
+ IntoStaticChunkIterator<consts::U12>
+ IntoStaticChunkIterator<consts::U13>
+ IntoStaticChunkIterator<consts::U14>
+ IntoStaticChunkIterator<consts::U15>
+ IntoStaticChunkIterator<consts::U16>
{
}
impl<T> StaticallySplittable for T where
T: IntoStaticChunkIterator<consts::U2>
+ IntoStaticChunkIterator<consts::U3>
+ IntoStaticChunkIterator<consts::U4>
+ IntoStaticChunkIterator<consts::U5>
+ IntoStaticChunkIterator<consts::U6>
+ IntoStaticChunkIterator<consts::U7>
+ IntoStaticChunkIterator<consts::U8>
+ IntoStaticChunkIterator<consts::U9>
+ IntoStaticChunkIterator<consts::U10>
+ IntoStaticChunkIterator<consts::U11>
+ IntoStaticChunkIterator<consts::U12>
+ IntoStaticChunkIterator<consts::U13>
+ IntoStaticChunkIterator<consts::U14>
+ IntoStaticChunkIterator<consts::U15>
+ IntoStaticChunkIterator<consts::U16>
{
}
pub trait ReadSet<'a>:
Set
+ View<'a>
+ Get<'a, usize>
+ Get<'a, std::ops::Range<usize>>
+ Isolate<usize>
+ Isolate<std::ops::Range<usize>>
+ IntoOwned
+ IntoOwnedData
+ SplitAt
+ SplitOff
+ SplitFirst
+ IntoStorage
+ Dummy
+ RemovePrefix
+ IntoChunkIterator
+ StaticallySplittable
+ Viewed
+ IntoIterator
{
}
impl<'a, T> ReadSet<'a> for T where
T: Set
+ View<'a>
+ Get<'a, usize>
+ Get<'a, std::ops::Range<usize>>
+ Isolate<usize>
+ Isolate<std::ops::Range<usize>>
+ IntoOwned
+ IntoOwnedData
+ SplitAt
+ SplitOff
+ SplitFirst
+ IntoStorage
+ Dummy
+ RemovePrefix
+ IntoChunkIterator
+ StaticallySplittable
+ Viewed
+ IntoIterator
{
}
pub trait WriteSet<'a>: ReadSet<'a> + ViewMut<'a> {}
impl<'a, T> WriteSet<'a> for T where T: ReadSet<'a> + ViewMut<'a> {}
pub trait OwnedSet<'a>:
Set
+ View<'a>
+ ViewMut<'a>
+ Get<'a, usize>
+ Get<'a, std::ops::Range<usize>>
+ Isolate<usize>
+ Isolate<std::ops::Range<usize>>
+ IntoOwned
+ IntoOwnedData
+ SplitOff
+ IntoStorage
+ Dummy
+ RemovePrefix
+ IntoChunkIterator
+ StaticallySplittable
+ ValueType
{
}
impl<'a, T> OwnedSet<'a> for T where
T: Set
+ View<'a>
+ ViewMut<'a>
+ Get<'a, usize>
+ Get<'a, std::ops::Range<usize>>
+ Isolate<usize>
+ Isolate<std::ops::Range<usize>>
+ IntoOwned
+ IntoOwnedData
+ SplitOff
+ IntoStorage
+ Dummy
+ RemovePrefix
+ IntoChunkIterator
+ StaticallySplittable
+ ValueType
{
}
pub trait Push<T> {
fn push(&mut self, element: T);
}
pub trait ExtendFromSlice {
type Item;
fn extend_from_slice(&mut self, other: &[Self::Item]);
}
pub trait Truncate {
fn truncate(&mut self, len: usize);
}
pub trait Clear {
fn clear(&mut self);
}
pub trait IntoStorage {
type StorageType;
fn into_storage(self) -> Self::StorageType;
}
pub trait StorageInto<Target> {
type Output;
fn storage_into(self) -> Self::Output;
}
pub trait MapStorage<Out> {
type Input;
type Output;
fn map_storage<F: FnOnce(Self::Input) -> Out>(self, f: F) -> Self::Output;
}
pub trait CloneWithStorage<S> {
type CloneType;
fn clone_with_storage(&self, storage: S) -> Self::CloneType;
}
pub trait IntoOwned
where
Self: Sized,
{
type Owned;
fn into_owned(self) -> Self::Owned;
#[inline]
fn clone_into(self, target: &mut Self::Owned) {
*target = self.into_owned();
}
}
impl<S: std::borrow::ToOwned + ?Sized> IntoOwned for &S {
type Owned = S::Owned;
#[inline]
fn into_owned(self) -> Self::Owned {
std::borrow::ToOwned::to_owned(self)
}
}
impl<S: std::borrow::ToOwned + ?Sized> IntoOwned for &mut S {
type Owned = S::Owned;
#[inline]
fn into_owned(self) -> Self::Owned {
std::borrow::ToOwned::to_owned(self)
}
}
pub trait IntoOwnedData
where
Self: Sized,
{
type OwnedData;
fn into_owned_data(self) -> Self::OwnedData;
#[inline]
fn clone_into(self, target: &mut Self::OwnedData) {
*target = self.into_owned_data();
}
}
impl<S: std::borrow::ToOwned + ?Sized> IntoOwnedData for &S {
type OwnedData = S::Owned;
#[inline]
fn into_owned_data(self) -> Self::OwnedData {
std::borrow::ToOwned::to_owned(self)
}
}
impl<S: std::borrow::ToOwned + ?Sized> IntoOwnedData for &mut S {
type OwnedData = S::Owned;
#[inline]
fn into_owned_data(self) -> Self::OwnedData {
std::borrow::ToOwned::to_owned(self)
}
}
pub trait IntBound:
std::ops::Sub<Self, Output = Self>
+ std::ops::Add<usize, Output = Self>
+ Into<usize>
+ From<usize>
+ Clone
{
}
impl<T> IntBound for T where
T: std::ops::Sub<Self, Output = Self>
+ std::ops::Add<usize, Output = Self>
+ Into<usize>
+ From<usize>
+ Clone
{
}
pub trait BoundedRange {
type Index: IntBound;
fn start(&self) -> Self::Index;
fn end(&self) -> Self::Index;
#[inline]
fn distance(&self) -> Self::Index {
self.end() - self.start()
}
}
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct StaticRange<N> {
pub start: usize,
pub phantom: std::marker::PhantomData<N>,
}
impl<N> StaticRange<N> {
#[inline]
pub fn new(start: usize) -> Self {
StaticRange {
start,
phantom: std::marker::PhantomData,
}
}
}
impl<N: Unsigned> BoundedRange for StaticRange<N> {
type Index = usize;
#[inline]
fn start(&self) -> usize {
self.start
}
#[inline]
fn end(&self) -> usize {
self.start + N::to_usize()
}
}
pub trait GetIndex<'a, S>
where
S: ?Sized,
{
type Output;
fn get(self, set: &S) -> Option<Self::Output>;
#[inline]
unsafe fn at_unchecked(self, set: &S) -> Self::Output
where
Self: Sized,
{
self.get(set).expect("Index out of bounds")
}
}
pub trait IsolateIndex<S> {
type Output;
fn try_isolate(self, set: S) -> Option<Self::Output>;
unsafe fn isolate_unchecked(self, set: S) -> Self::Output;
}
pub trait Get<'a, I> {
type Output;
fn get(&self, idx: I) -> Option<Self::Output>;
#[inline]
fn at(&self, idx: I) -> Self::Output {
self.get(idx).expect("Index out of bounds")
}
#[inline]
unsafe fn at_unchecked(&self, idx: I) -> Self::Output {
self.at(idx)
}
}
impl<'a, S, I> Get<'a, I> for S
where
I: GetIndex<'a, Self>,
{
type Output = I::Output;
#[inline]
fn get(&self, idx: I) -> Option<I::Output> {
idx.get(self)
}
}
pub trait Isolate<I> {
type Output;
unsafe fn isolate_unchecked(self, idx: I) -> Self::Output;
fn try_isolate(self, idx: I) -> Option<Self::Output>;
#[inline]
fn isolate(self, idx: I) -> Self::Output
where
Self: Sized,
{
self.try_isolate(idx).expect("Index out of bounds")
}
}
impl<S, I> Isolate<I> for S
where
I: IsolateIndex<Self>,
{
type Output = I::Output;
#[inline]
unsafe fn isolate_unchecked(self, idx: I) -> Self::Output {
idx.isolate_unchecked(self)
}
#[inline]
fn try_isolate(self, idx: I) -> Option<Self::Output> {
idx.try_isolate(self)
}
}
impl<'a, S, N> GetIndex<'a, S> for StaticRange<N>
where
S: Set + DynamicRangeIndexType,
N: Unsigned,
std::ops::Range<usize>: GetIndex<'a, S>,
{
type Output = <std::ops::Range<usize> as GetIndex<'a, S>>::Output;
#[inline]
fn get(self, set: &S) -> Option<Self::Output> {
(self.start..self.start + N::to_usize()).get(set)
}
}
impl<'a, S> GetIndex<'a, S> for std::ops::RangeFrom<usize>
where
S: Set + ValueType,
std::ops::Range<usize>: GetIndex<'a, S>,
{
type Output = <std::ops::Range<usize> as GetIndex<'a, S>>::Output;
#[inline]
fn get(self, set: &S) -> Option<Self::Output> {
(self.start..set.len()).get(set)
}
}
impl<'a, S: ValueType> GetIndex<'a, S> for std::ops::RangeTo<usize>
where
std::ops::Range<usize>: GetIndex<'a, S>,
{
type Output = <std::ops::Range<usize> as GetIndex<'a, S>>::Output;
#[inline]
fn get(self, set: &S) -> Option<Self::Output> {
(0..self.end).get(set)
}
}
impl<'a, S> GetIndex<'a, S> for std::ops::RangeFull
where
S: Set + ValueType,
std::ops::Range<usize>: GetIndex<'a, S>,
{
type Output = <std::ops::Range<usize> as GetIndex<'a, S>>::Output;
#[inline]
fn get(self, set: &S) -> Option<Self::Output> {
(0..set.len()).get(set)
}
}
impl<'a, S: ValueType> GetIndex<'a, S> for std::ops::RangeInclusive<usize>
where
std::ops::Range<usize>: GetIndex<'a, S>,
{
type Output = <std::ops::Range<usize> as GetIndex<'a, S>>::Output;
#[allow(clippy::range_plus_one)]
#[inline]
fn get(self, set: &S) -> Option<Self::Output> {
if *self.end() == usize::max_value() {
None
} else {
(*self.start()..*self.end() + 1).get(set)
}
}
}
impl<'a, S: ValueType> GetIndex<'a, S> for std::ops::RangeToInclusive<usize>
where
std::ops::Range<usize>: GetIndex<'a, S>,
{
type Output = <std::ops::Range<usize> as GetIndex<'a, S>>::Output;
#[inline]
fn get(self, set: &S) -> Option<Self::Output> {
(0..=self.end).get(set)
}
}
impl<S, N> IsolateIndex<S> for StaticRange<N>
where
S: Set + DynamicRangeIndexType,
N: Unsigned,
std::ops::Range<usize>: IsolateIndex<S>,
{
type Output = <std::ops::Range<usize> as IsolateIndex<S>>::Output;
#[inline]
unsafe fn isolate_unchecked(self, set: S) -> Self::Output {
IsolateIndex::isolate_unchecked(self.start..self.start + N::to_usize(), set)
}
#[inline]
fn try_isolate(self, set: S) -> Option<Self::Output> {
IsolateIndex::try_isolate(self.start..self.start + N::to_usize(), set)
}
}
impl<S> IsolateIndex<S> for std::ops::RangeFrom<usize>
where
S: Set + ValueType,
std::ops::Range<usize>: IsolateIndex<S>,
{
type Output = <std::ops::Range<usize> as IsolateIndex<S>>::Output;
#[inline]
unsafe fn isolate_unchecked(self, set: S) -> Self::Output {
IsolateIndex::isolate_unchecked(self.start..set.len(), set)
}
#[inline]
fn try_isolate(self, set: S) -> Option<Self::Output> {
IsolateIndex::try_isolate(self.start..set.len(), set)
}
}
impl<S: ValueType> IsolateIndex<S> for std::ops::RangeTo<usize>
where
std::ops::Range<usize>: IsolateIndex<S>,
{
type Output = <std::ops::Range<usize> as IsolateIndex<S>>::Output;
#[inline]
unsafe fn isolate_unchecked(self, set: S) -> Self::Output {
IsolateIndex::isolate_unchecked(0..self.end, set)
}
#[inline]
fn try_isolate(self, set: S) -> Option<Self::Output> {
IsolateIndex::try_isolate(0..self.end, set)
}
}
impl<S: ValueType> IsolateIndex<S> for std::ops::RangeFull
where
S: Set,
std::ops::Range<usize>: IsolateIndex<S>,
{
type Output = <std::ops::Range<usize> as IsolateIndex<S>>::Output;
#[inline]
unsafe fn isolate_unchecked(self, set: S) -> Self::Output {
IsolateIndex::isolate_unchecked(0..set.len(), set)
}
#[inline]
fn try_isolate(self, set: S) -> Option<Self::Output> {
IsolateIndex::try_isolate(0..set.len(), set)
}
}
impl<S: ValueType> IsolateIndex<S> for std::ops::RangeInclusive<usize>
where
S: Set,
std::ops::Range<usize>: IsolateIndex<S>,
{
type Output = <std::ops::Range<usize> as IsolateIndex<S>>::Output;
#[allow(clippy::range_plus_one)]
#[inline]
unsafe fn isolate_unchecked(self, set: S) -> Self::Output {
IsolateIndex::isolate_unchecked(*self.start()..*self.end() + 1, set)
}
#[allow(clippy::range_plus_one)]
#[inline]
fn try_isolate(self, set: S) -> Option<Self::Output> {
if *self.end() == usize::max_value() {
None
} else {
IsolateIndex::try_isolate(*self.start()..*self.end() + 1, set)
}
}
}
impl<S: ValueType> IsolateIndex<S> for std::ops::RangeToInclusive<usize>
where
S: Set,
std::ops::Range<usize>: IsolateIndex<S>,
{
type Output = <std::ops::Range<usize> as IsolateIndex<S>>::Output;
#[inline]
unsafe fn isolate_unchecked(self, set: S) -> Self::Output {
IsolateIndex::isolate_unchecked(0..=self.end, set)
}
#[inline]
fn try_isolate(self, set: S) -> Option<Self::Output> {
IsolateIndex::try_isolate(0..=self.end, set)
}
}
pub trait SplitAt
where
Self: Sized,
{
fn split_at(self, mid: usize) -> (Self, Self);
}
pub trait SplitOff {
fn split_off(&mut self, mid: usize) -> Self;
}
pub trait SplitPrefix<N>
where
Self: Sized,
{
type Prefix;
fn split_prefix(self) -> Option<(Self::Prefix, Self)>;
}
pub trait SplitFirst
where
Self: Sized,
{
type First;
fn split_first(self) -> Option<(Self::First, Self)>;
#[inline]
unsafe fn split_first_unchecked(self) -> (Self::First, Self) {
self.split_first().unwrap()
}
}
pub trait Storage {
type Storage: ?Sized;
fn storage(&self) -> &Self::Storage;
}
impl<S: Storage + ?Sized> Storage for &S {
type Storage = S::Storage;
#[inline]
fn storage(&self) -> &Self::Storage {
S::storage(*self)
}
}
impl<S: Storage + ?Sized> Storage for &mut S {
type Storage = S::Storage;
#[inline]
fn storage(&self) -> &Self::Storage {
S::storage(*self)
}
}
pub trait StorageView<'a> {
type StorageView;
fn storage_view(&'a self) -> Self::StorageView;
}
pub trait StorageMut: Storage {
fn storage_mut(&mut self) -> &mut Self::Storage;
}
impl<S: StorageMut + ?Sized> StorageMut for &mut S {
#[inline]
fn storage_mut(&mut self) -> &mut Self::Storage {
S::storage_mut(*self)
}
}
pub trait Dummy {
unsafe fn dummy() -> Self;
}
pub trait RemovePrefix {
fn remove_prefix(&mut self, n: usize);
}
pub trait IntoChunkIterator {
type Item;
type IterType: Iterator<Item = Self::Item>;
fn into_chunk_iter(self, chunk_size: usize) -> Self::IterType;
}
impl<S> IntoChunkIterator for S
where
S: Set + SplitAt + Dummy,
{
type Item = S;
type IterType = ChunkedNIter<S>;
#[inline]
fn into_chunk_iter(self, chunk_size: usize) -> Self::IterType {
assert_eq!(self.len() % chunk_size, 0);
ChunkedNIter {
chunk_size,
data: self,
}
}
}
#[cfg(feature = "rayon")]
pub trait IntoParChunkIterator {
type Item: Send;
type IterType: rayon::iter::IndexedParallelIterator<Item = Self::Item>;
fn into_par_chunk_iter(self, chunk_size: usize) -> Self::IterType;
}
pub trait UniChunkable<N> {
type Chunk;
}
pub trait IntoStaticChunkIterator<N>
where
Self: Sized + Set,
N: Unsigned,
{
type Item;
type IterType: Iterator<Item = Self::Item>;
fn into_static_chunk_iter(self) -> Self::IterType;
#[inline]
fn into_generic_static_chunk_iter(self) -> UniChunkedIter<Self, N> {
assert_eq!(self.len() % N::to_usize(), 0);
UniChunkedIter {
chunk_size: std::marker::PhantomData,
data: self,
}
}
}
pub trait Reserve {
#[inline]
fn reserve(&mut self, n: usize) {
self.reserve_with_storage(n, 0); }
fn reserve_with_storage(&mut self, n: usize, storage_n: usize);
}
pub trait SwapChunks {
fn swap_chunks(&mut self, begin_a: usize, begin_b: usize, chunk_size: usize);
}
pub trait Sort {
fn sort_indices(&self, indices: &mut [usize]);
}
pub trait PermuteInPlace {
fn permute_in_place(&mut self, indices: &[usize], seen: &mut [bool]);
}
pub trait ChunkSize {
fn chunk_size(&self) -> usize;
}
pub trait CloneIntoOther<T = Self>
where
T: ?Sized,
{
fn clone_into_other(&self, other: &mut T);
}
impl<T: Clone> CloneIntoOther<&mut T> for &T {
#[inline]
fn clone_into_other(&self, other: &mut &mut T) {
other.clone_from(self);
}
}
pub trait AtomIterator<'a> {
type Item;
type Iter: Iterator<Item = Self::Item>;
fn atom_iter(&'a self) -> Self::Iter;
}
pub trait AtomMutIterator<'a> {
type Item;
type Iter: Iterator<Item = Self::Item>;
fn atom_mut_iter(&'a mut self) -> Self::Iter;
}
impl<'a, S: ?Sized> AtomIterator<'a> for &S
where
S: AtomIterator<'a>,
{
type Item = S::Item;
type Iter = S::Iter;
#[inline]
fn atom_iter(&'a self) -> Self::Iter {
S::atom_iter(self)
}
}
impl<'a, S: ?Sized> AtomMutIterator<'a> for &mut S
where
S: AtomMutIterator<'a>,
{
type Item = S::Item;
type Iter = S::Iter;
#[inline]
fn atom_mut_iter(&'a mut self) -> Self::Iter {
S::atom_mut_iter(self)
}
}
pub struct StructIter<I, T> {
iter: I,
phantom: std::marker::PhantomData<T>,
}
impl<I, T> StructIter<I, T> {
#[inline]
pub fn new(iter: I) -> Self {
StructIter {
iter,
phantom: std::marker::PhantomData,
}
}
}
impl<I: Iterator, T: From<I::Item>> Iterator for StructIter<I, T> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(From::from)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.iter.nth(n).map(From::from)
}
}
impl<I, T> DoubleEndedIterator for StructIter<I, T>
where
I: DoubleEndedIterator + ExactSizeIterator,
T: From<I::Item>,
{
#[inline]
fn next_back(&mut self) -> Option<T> {
self.iter.next_back().map(From::from)
}
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
self.iter.nth_back(n).map(From::from)
}
}
pub unsafe trait TrustedRandomAccess: ExactSizeIterator {
unsafe fn get_unchecked(&mut self, index: usize) -> Self::Item;
#[inline]
fn may_have_side_effect() -> bool {
false
}
}
#[doc(hidden)]
pub fn multiple_mut_refs_compile_test() {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn var_of_uni_iter_test() {
let u0 = Chunked2::from_flat((1..=12).collect::<Vec<_>>());
let v1 = Chunked::from_offsets(vec![0, 2, 3, 6], u0);
let mut iter1 = v1.iter();
let v0 = iter1.next().unwrap();
let mut iter0 = v0.iter();
assert_eq!(Some(&[1, 2]), iter0.next());
assert_eq!(Some(&[3, 4]), iter0.next());
assert_eq!(None, iter0.next());
let v0 = iter1.next().unwrap();
let mut iter0 = v0.iter();
assert_eq!(Some(&[5, 6]), iter0.next());
assert_eq!(None, iter0.next());
let v0 = iter1.next().unwrap();
let mut iter0 = v0.iter();
assert_eq!(Some(&[7, 8]), iter0.next());
assert_eq!(Some(&[9, 10]), iter0.next());
assert_eq!(Some(&[11, 12]), iter0.next());
assert_eq!(None, iter0.next());
}
#[cfg(feature = "derive")]
mod derive_tests {
use super::*;
use crate as flatk;
use flatk::Component;
#[derive(Copy, Clone, Debug, PartialEq, Component)]
struct MyComponent<X, V> {
id: usize,
x: X,
v: V,
}
#[test]
fn component_derive_test() {
let mut e = MyComponent {
id: 0,
x: vec![1.0; 12],
v: vec![7.0; 12],
};
assert_eq!(e.len(), 12);
assert_eq!(
e.view().at(0),
MyComponent {
id: 0,
x: &1.0,
v: &7.0
}
);
let entry_mut = e.view_mut().isolate(0);
*entry_mut.x = 13.0;
*entry_mut.v = 14.0;
assert_eq!(
e.view().at(0),
MyComponent {
id: 0,
x: &13.0,
v: &14.0
}
);
let chunked3 = Chunked3::from_flat(e.clone());
assert_eq!(
chunked3.view().at(0),
MyComponent {
id: 0,
x: &[13.0, 1.0, 1.0],
v: &[14.0, 7.0, 7.0]
}
);
let chunked = Chunked::from_sizes(vec![1, 3], Chunked3::from_flat(e));
assert_eq!(
chunked.view().at(0).at(0),
MyComponent {
id: 0,
x: &[13.0, 1.0, 1.0],
v: &[14.0, 7.0, 7.0]
}
);
}
}
}