use super::FromComponent;
use std::ops::Deref;
pub struct ReadOr<'a, T: TupleAny<'a>> {
component: <T as TupleAny<'a>>::AnyTarget,
}
impl<'a, T: TupleAny<'a>> FromComponent<'a, <T as TupleAny<'a>>::AnyTarget> for ReadOr<'a,T> {
fn from_component(component: <T as TupleAny<'a>>::AnyTarget) -> ReadOr<'a,T>{
ReadOr{
component
}
}
}
impl<'a, T: TupleAny<'a>> Deref for ReadOr<'a, T>{
type Target = <T as TupleAny<'a>>::AnyTarget;
fn deref(&self) -> &<T as TupleAny<'a>>::AnyTarget {
&self.component
}
}
pub trait TupleAny<'a> {
type AnyTarget;
}
macro_rules! impl_or_iter {
($intoiter_or: ident, $iter_or: ident, $storage_or: ident, $($t: ident, $s: ident, $bs: ident, $id: ident, $tid: ident),*) => (
impl<'a, $($t: Component),*> super::TupleAny<'a> for ($($t),*)
where $(<$t as Component>::Storage: Storage<'a, $t>),*
{
type AnyTarget = ($(Option<<<$t as Component>::Storage as Storage<'a, $t>>::Get>),*);
}
pub struct $iter_or<'a, $($t, $bs),*, I> {
ptr: *const HiddenFastIndex,
end: *const HiddenFastIndex,
storage: $storage_or<'a, $($t, $bs,)* I>,
}
impl<'a, I, $($t, $bs),*> Iterator for $iter_or<'a, $($t, $bs),*, I>
where
$(for<'s> $t::Storage: Storage<'s, $t>,)*
$($t: Component,)*
$($bs: Deref<Target = $t::Storage>,)*
{
type Item = ($(Option<<$t::Storage as Storage<'a, $t>>::Get>),*);
fn next(&mut self) -> Option<Self::Item>{
unsafe {
if self.ptr == self.end {
None
} else {
let ids = &*self.ptr;
let ids = ids.unchecked_downcast_ref();
self.ptr = self.ptr.offset(1);
let ($($id),*): &($(Option<$tid>),*) = ids;
Some(($($id.and_then(|idx| self.storage.$bs.as_ref().map(|s| s.fast_get(idx)))),*))
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.end as usize - self.ptr as usize;
(len, Some(len))
}
}
impl<'a, I, $($t, $bs),*> ExactSizeIterator for $iter_or<'a, $($t, $bs),*, I>
where
$(for<'s> $t::Storage: Storage<'s, $t>,)*
$($t: Component,)*
$($bs: Deref<Target = $t::Storage>,)*
{
#[inline]
fn len(&self) -> usize {
self.end as usize - self.ptr as usize
}
}
#[allow(non_snake_case, dead_code)]
pub struct $storage_or<'a, $($t, $bs,)* I>
{
ids: I,
$(
$bs: Option<$bs>,
$t: marker::PhantomData<$t>,
)*
marker: marker::PhantomData<&'a ()>,
}
impl<'a, I, $($t, $bs,)*> FastIndexExt for $storage_or<'a, $($t, $bs,)* I>
where
$(for<'s> $t::Storage: Storage<'s, $t>,)*
$($t: Component,)*
$($bs: Deref<Target = $t::Storage>,)*
{
type FastIndex = ($(Option<$tid>),*);
type StaticTypeId = ($($t),*);
fn fast_index(&self, guid: usize) -> ($(Option<$tid>),*) {
($({
self.$bs.as_ref().and_then(|s|
if s.contains(guid) {
Some(s.fast_index(guid))
}else{
None
}
)
}),*)
}
}
impl<'a, 'r, I, $($t, $bs),*> StorageRef<'r> for $storage_or<'a, $($t, $bs,)* I>
where
$(for<'s> $t::Storage: Storage<'s, $t>,)*
$($t: Component,)*
$($bs: Deref<Target = $t::Storage>,)*
{
type Component = ($(Option<<$t::Storage as Storage<'r,$t>>::Get>),*);
type Data = ReadOr<'a, ($($t),*)>;
unsafe fn get_fast_unchecked(&mut self, idx: ($(Option<$tid>),*)) -> Self::Component {
let ($($id),*) = idx;
($($id.and_then(|idx| self.$bs.as_ref().map(|s| s.fast_get(idx)))),*)
}
#[allow(non_snake_case)]
unsafe fn get_unchecked(&mut self, guid: usize) -> Self::Component {
$(
let $t = self.$bs.as_ref().and_then(|s| {
let $s = delete_lifetime(s);
if $s.contains(guid) {
Some($s.get(guid))
}else{
None
}
});
)*
($($t),*)
}
fn contains(&self, guid: usize) -> bool{
$(self.$bs.as_ref().map(|s| s.contains(guid)).unwrap_or(false)) | *
}
}
impl<'a, 'r, $($t, $bs,)* I> IntoSendStorage<'r> for $storage_or<'a, $($t, $bs,)* I>
where
$(for<'s> $t::Storage: Storage<'s, $t> + 'r,)*
$($t: Component,)*
$($bs: Deref<Target = $t::Storage>,)*
I: Indices
{
type SendStorage = $storage_or<'a, $($t, &'r $t::Storage,)* &'r [HiddenFastIndex]>;
fn into_send_storage(&'r mut self) -> Self::SendStorage {
$storage_or{
ids: self.ids.index(self),
$(
$bs: self.$bs.as_deref(),
$t: marker::PhantomData,
)*
marker: marker::PhantomData,
}
}
}
unsafe impl<'a, I ,$($t, $bs),*> ReadOnlyStorage for $storage_or<'a, $($t, $bs,)* I>{}
impl<'a, 'i, 'r, $($t, $bs,)* I> OptionStorage<'r> for $storage_or<'a, $($t, $bs,)* I>
where
$(for<'s> $t::Storage: Storage<'s, $t>,)*
$($t: Component,)*
$($bs: Deref<Target = $t::Storage>,)*
I: Indices
{
type Iter = $iter_or<'r, $($t, &'r $t::Storage),*, Option<&'r [HiddenFastIndex]>>;
fn iter(this: Option<&'r Self>) -> Self::Iter {
let ptr_range = this
.map(|s| s.ids.as_ptr_range(s))
.unwrap_or(ptr::null() .. ptr::null());
$iter_or{
ptr: ptr_range.start,
end: ptr_range.end,
storage: $storage_or{
ids: this.map(|storage| storage.ids.index(storage)),
$(
$bs: this.and_then(|storage| storage.$bs.as_deref()),
$t: marker::PhantomData,
)*
marker: marker::PhantomData,
},
}
}
}
unsafe impl<'a, $($t: Component),*> SafeIter<'a> for ReadOr<'a,($($t),*)>
where $(<$t as Component>::Storage: Storage<'a, $t>),*{}
impl<'a, $($t: Component + Send),*> UnorderedData<'a> for ReadOr<'a,($($t),*)>
where $(for<'s> <$t as Component>::Storage: Storage<'s, $t>),*
{
type Iter = $iter_or<'a, $(
$t,
ReadGuardRef<'a, <$t as Component>::Storage>,)*
LazyIndexGuard<'a>
>;
type IterMut = $iter_or<'a, $(
$t,
ReadGuardRef<'a, <$t as Component>::Storage>,)*
LazyIndexGuard<'a>
>;
type Components = ($($t,)*);
type ComponentsRef = ($(Option<<<$t as Component>::Storage as Storage<'a, $t>>::Get>),*);
type Storage = $storage_or<'a, $(
$t,
ReadGuardRef<'a, <$t as Component>::Storage>,)*
LazyIndexGuard<'a>
>;
fn query_mask<E: EntitiesStorage>(entities: &E) -> Bitmask {
Bitmask::or($(entities.component_mask::<$t>()) | *)
}
fn into_iter<E: EntitiesStorage>(entities: &'a E) -> Self::Iter {
let storage = <Self as UnorderedData>::storage(entities).unwrap();
$iter_or{
ptr: storage.ids.index(&storage).as_ptr(),
end: unsafe{ storage.ids.index(&storage).as_ptr().add(storage.ids.index(&storage).len()) },
storage,
}
}
fn into_iter_mut<E: EntitiesStorage>(entities: &'a E) -> Self::Iter {
Self::into_iter(entities)
}
fn storage<E: EntitiesStorage>(entities: &'a E) -> Option<Self::Storage> {
let ids = entities.lazy_entities_for_mask(
<Self as UnorderedData>::query_mask(entities),
);
Some($storage_or {
ids,
$(
$bs: entities.storage::<$t>(),
$t: marker::PhantomData,
)*
marker: marker::PhantomData,
})
}
}
impl<'a, $($t: Component),*> DataAccesses for ReadOr<'a,($($t),*)>
where $(<$t as Component>::Storage: Storage<'a, $t>),*
{
fn reads() -> Vec<TypeId>{ vec![$(TypeId::of::<$t>(),)*] }
fn writes() -> Vec<TypeId>{ vec![] }
}
)}
mod or_storage{
use std::{marker, ptr};
use crate::storage::{
StorageRef, IntoSendStorage, Storage, FastIndexExt, HiddenFastIndex, ReadOnlyStorage
};
use crate::operators::{UnorderedData, DataAccesses, SafeIter, OptionStorage};
use crate::component::Component;
use crate::entity::EntitiesStorage;
use crate::bitmask::Bitmask;
use super::ReadOr;
use crate::sync::{ReadGuardRef, LazyIndexGuard, Indices};
use crate::utils::delete_lifetime;
use std::ops::Deref;
use std::any::TypeId;
#[cfg(any(feature="storage_macros_2", feature="storage_macros_4", feature="storage_macros_8", feature="storage_macros_16"))]
impl_or_iter!(IntoIter2, Iter2, StorageRef2, T1, S1, BS1, id1, usize, T2, S2, BS2, id2, usize);
#[cfg(any(feature="storage_macros_4", feature="storage_macros_8", feature="storage_macros_16"))]
impl_or_iter!(IntoIter3, Iter3, StorageRef3, T1, S1, BS1, id1, usize, T2, S2, BS2, id2, usize, T3, S3, BS3, id3, usize);
#[cfg(any(feature="storage_macros_4", feature="storage_macros_8", feature="storage_macros_16"))]
impl_or_iter!(IntoIter4, Iter4, StorageRef4, T1, S1, BS1, id1, usize, T2, S2, BS2, id2, usize, T3, S3, BS3, id3, usize, T4, S4, BS4, id4, usize);
#[cfg(any(feature="storage_macros_8", feature="storage_macros_16"))]
impl_or_iter!(IntoIter5, Iter5, StorageRef5, T1, S1, BS1, id1, usize, T2, S2, BS2, id2, usize, T3, S3, BS3, id3, usize, T4, S4, BS4, id4, usize, T5, S5, BS5, id5, usize);
#[cfg(any(feature="storage_macros_8", feature="storage_macros_16"))]
impl_or_iter!(IntoIter6, Iter6, StorageRef6, T1, S1, BS1, id1, usize, T2, S2, BS2, id2, usize, T3, S3, BS3, id3, usize, T4, S4, BS4, id4, usize, T5, S5, BS5, id5, usize, T6, S6, BS6, id6, usize);
#[cfg(any(feature="storage_macros_8", feature="storage_macros_16"))]
impl_or_iter!(IntoIter7, Iter7, StorageRef7, T1, S1, BS1, id1, usize, T2, S2, BS2, id2, usize, T3, S3, BS3, id3, usize, T4, S4, BS4, id4, usize, T5, S5, BS5, id5, usize, T6, S6, BS6, id6, usize, T7, S7, BS7, id7, usize);
#[cfg(any(feature="storage_macros_8", feature="storage_macros_16"))]
impl_or_iter!(IntoIter8, Iter8, StorageRef8, T1, S1, BS1, id1, usize, T2, S2, BS2, id2, usize, T3, S3, BS3, id3, usize, T4, S4, BS4, id4, usize, T5, S5, BS5, id5, usize, T6, S6, BS6, id6, usize, T7, S7, BS7, id7, usize, T8, S8, BS8, id8, usize);
#[cfg(any(feature="storage_macros_16"))]
impl_or_iter!(IntoIter9, Iter9, StorageRef9, T1, S1, BS1, id1, usize, T2, S2, BS2, id2, usize, T3, S3, BS3, id3, usize, T4, S4, BS4, id4, usize, T5, S5, BS5, id5, usize, T6, S6, BS6, id6, usize, T7, S7, BS7, id7, usize, T8, S8, BS8, id8, usize, T9, S9, BS9, id9, usize);
#[cfg(any(feature="storage_macros_16"))]
impl_or_iter!(IntoIter10, Iter10, StorageRef10, T1, S1, BS1, id1, usize, T2, S2, BS2, id2, usize, T3, S3, BS3, id3, usize, T4, S4, BS4, id4, usize, T5, S5, BS5, id5, usize, T6, S6, BS6, id6, usize, T7, S7, BS7, id7, usize, T8, S8, BS8, id8, usize, T9, S9, BS9, id9, usize, T10, S10, BS10, id10, usize);
#[cfg(any(feature="storage_macros_16"))]
impl_or_iter!(IntoIter11, Iter11, StorageRef11, T1, S1, BS1, id1, usize, T2, S2, BS2, id2, usize, T3, S3, BS3, id3, usize, T4, S4, BS4, id4, usize, T5, S5, BS5, id5, usize, T6, S6, BS6, id6, usize, T7, S7, BS7, id7, usize, T8, S8, BS8, id8, usize, T9, S9, BS9, id9, usize, T10, S10, BS10, id10, usize, T11, S11, BS11, id11, usize);
#[cfg(any(feature="storage_macros_16"))]
impl_or_iter!(IntoIter12, Iter12, StorageRef12, T1, S1, BS1, id1, usize, T2, S2, BS2, id2, usize, T3, S3, BS3, id3, usize, T4, S4, BS4, id4, usize, T5, S5, BS5, id5, usize, T6, S6, BS6, id6, usize, T7, S7, BS7, id7, usize, T8, S8, BS8, id8, usize, T9, S9, BS9, id9, usize, T10, S10, BS10, id10, usize, T11, S11, BS11, id11, usize, T12, S12, BS12, id12, usize);
#[cfg(any(feature="storage_macros_16"))]
impl_or_iter!(IntoIter13, Iter13, StorageRef13, T1, S1, BS1, id1, usize, T2, S2, BS2, id2, usize, T3, S3, BS3, id3, usize, T4, S4, BS4, id4, usize, T5, S5, BS5, id5, usize, T6, S6, BS6, id6, usize, T7, S7, BS7, id7, usize, T8, S8, BS8, id8, usize, T9, S9, BS9, id9, usize, T10, S10, BS10, id10, usize, T11, S11, BS11, id11, usize, T12, S12, BS12, id12, usize, T13, S13, BS13, id13, usize);
#[cfg(any(feature="storage_macros_16"))]
impl_or_iter!(IntoIter14, Iter14, StorageRef14, T1, S1, BS1, id1, usize, T2, S2, BS2, id2, usize, T3, S3, BS3, id3, usize, T4, S4, BS4, id4, usize, T5, S5, BS5, id5, usize, T6, S6, BS6, id6, usize, T7, S7, BS7, id7, usize, T8, S8, BS8, id8, usize, T9, S9, BS9, id9, usize, T10, S10, BS10, id10, usize, T11, S11, BS11, id11, usize, T12, S12, BS12, id12, usize, T13, S13, BS13, id13, usize, T14, S14, BS14, id14, usize);
#[cfg(any(feature="storage_macros_16"))]
impl_or_iter!(IntoIter15, Iter15, StorageRef15, T1, S1, BS1, id1, usize, T2, S2, BS2, id2, usize, T3, S3, BS3, id3, usize, T4, S4, BS4, id4, usize, T5, S5, BS5, id5, usize, T6, S6, BS6, id6, usize, T7, S7, BS7, id7, usize, T8, S8, BS8, id8, usize, T9, S9, BS9, id9, usize, T10, S10, BS10, id10, usize, T11, S11, BS11, id11, usize, T12, S12, BS12, id12, usize, T13, S13, BS13, id13, usize, T14, S14, BS14, id14, usize, T15, S15, BS15, id15, usize);
#[cfg(any(feature="storage_macros_16"))]
impl_or_iter!(IntoIter16, Iter16, StorageRef16, T1, S1, BS1, id1, usize, T2, S2, BS2, id2, usize, T3, S3, BS3, id3, usize, T4, S4, BS4, id4, usize, T5, S5, BS5, id5, usize, T6, S6, BS6, id6, usize, T7, S7, BS7, id7, usize, T8, S8, BS8, id8, usize, T9, S9, BS9, id9, usize, T10, S10, BS10, id10, usize, T11, S11, BS11, id11, usize, T12, S12, BS12, id12, usize, T13, S13, BS13, id13, usize, T14, S14, BS14, id14, usize, T15, S15, BS15, id15, usize, T16, S16, BS16, id16, usize);
}