use std::{marker, ptr};
use crate::{bitmask::{Bitmask, MaskType}, component::Component, entity::{Entity, EntitiesStorage}, storage::{IntoSendStorage, FastIndexExt, Storage, StorageRef, ReadOnlyStorage}, sync::ReadGuardRef};
use super::{DataAccesses, FromComponent, OptionStorage, SafeIter, UnorderedData};
#[cfg(feature="parallel_iter")]
use super::ParOptionStorage;
use std::ops::Deref;
#[cfg(feature = "parallel_iter")]
use rayon::prelude::*;
#[cfg(feature = "parallel_iter")]
use rayon::iter::plumbing::UnindexedConsumer;
use std::usize;
use std::any::TypeId;
use unchecked_unwrap::*;
type Get<'a, T> = <<T as Component>::Storage as Storage<'a, T>>::Get;
pub struct ReadOption<'a, T: Component>
where for<'s> <T as Component>::Storage: Storage<'s, T>
{
component: Option<Get<'a,T>>,
}
impl<'a, T: Component> FromComponent<'a, Option<Get<'a,T>>> for ReadOption<'a, T>
where for<'s> <T as Component>::Storage: Storage<'s, T>
{
fn from_component(component: Option<Get<'a,T>>) -> ReadOption<'a,T>{
ReadOption{
component,
}
}
}
impl<'a, T: Component> Deref for ReadOption<'a, T>
where for<'s> <T as Component>::Storage: Storage<'s, T>
{
type Target = Option<Get<'a,T>>;
fn deref(&self) -> &Option<Get<'a,T>>{
&self.component
}
}
pub struct IterOption<'a, T, S, BS> {
ptr: *const (Entity, MaskType),
end: *const (Entity, MaskType),
storage: StorageOption<'a, T, S, BS>,
}
impl<'a, 'r, T, S, BS> Iterator for IterOption<'a, T, S, BS>
where
for<'s> <T as Component>::Storage: Storage<'s, T>,
S: Storage<'a, T>,
BS: Deref<Target = S>,
T: Component,
{
type Item = Option<<S as crate::Storage<'a,T>>::Get>;
#[inline]
fn next(&mut self) -> Option<Self::Item>{
let storage = self.storage.storage.as_ref()?;
while self.ptr != self.end {
unsafe {
let (e, _) = &*self.ptr;
self.ptr = self.ptr.add(1);
if e.guid != usize::MAX {
if storage.contains(e.guid) {
return Some(Some(storage.get(e.guid)));
}else{
return Some(None)
}
}
}
}
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.end as usize - self.ptr as usize;
(0, Some(len))
}
}
pub struct StorageOption<'a, T, S, BS> {
storage: Option<BS>,
entities: &'a [(Entity, MaskType)],
_marker_t: marker::PhantomData<T>,
_marker_s: marker::PhantomData<S>,
}
unsafe impl<'a, T, S, BS> ReadOnlyStorage for StorageOption<'a, T, S, BS>{}
impl<'a, T, S, BS> FastIndexExt for StorageOption<'a, T, S, BS>
where
S: for<'s> Storage<'s,T>,
T: Component,
BS: Deref<Target = S>,
{
type FastIndex = Option<usize>;
type StaticTypeId = Option<T>;
fn fast_index(&self, guid: usize) -> Option<usize> {
let storage = self.storage.as_ref()?;
if storage.contains(guid) {
Some(storage.fast_index(guid))
}else{
None
}
}
}
impl<'a, 'r, T, S, BS> StorageRef<'r> for StorageOption<'a, T, S, BS>
where
for<'s> <T as Component>::Storage: Storage<'s, T>,
S: for<'s> Storage<'s,T>,
BS: Deref<Target = S>,
T: Component,
{
type Data = ReadOption<'a,T>;
type Component = Option<<S as Storage<'r,T>>::Get>;
unsafe fn get_fast_unchecked(&mut self, idx: Option<usize>) -> Option<<S as Storage<'r,T>>::Get>{
idx.and_then(|idx| self.storage.as_ref().map(|storage| storage.fast_get(idx)))
}
unsafe fn get_unchecked(&mut self, guid: usize) -> Option<<S as Storage<'r,T>>::Get>{
let storage = self.storage.as_ref()?;
if storage.contains(guid) {
Some(storage.get(guid))
}else{
None
}
}
fn contains(&self, _guid: usize) -> bool{
true
}
}
impl<'a, 'r, T, S, BS> IntoSendStorage<'r> for StorageOption<'a, T, S, BS>
where
for<'s> <T as Component>::Storage: Storage<'s, T>,
S: for<'s> Storage<'s,T> + 'r,
BS: Deref<Target = S>,
T: Component,
{
type SendStorage = StorageOption<'a, T, S, &'r S>;
fn into_send_storage(&'r mut self) -> Self::SendStorage {
StorageOption {
storage: self.storage.as_deref(),
entities: self.entities,
_marker_t: marker::PhantomData,
_marker_s: marker::PhantomData,
}
}
}
impl<'a, 'r, S, T> OptionStorage<'r> for StorageOption<'a, T, S, ReadGuardRef<'a, S>>
where
for<'s> <T as Component>::Storage: Storage<'s, T>,
S: for<'s> Storage<'s,T> + 'r,
T: Component,
{
type Iter = IterOption<'r, T, S, &'r S>;
fn iter(this: Option<&'r Self>) -> Self::Iter {
let ptr_range = this
.map(|s| s.entities.as_ptr_range())
.unwrap_or(ptr::null() .. ptr::null());
IterOption{
ptr: ptr_range.start,
end: ptr_range.end,
storage: StorageOption{
storage: this.and_then(|storage| storage.storage.as_deref()),
entities: this.map(|storage| storage.entities).unwrap_or(&[]),
_marker_t: marker::PhantomData,
_marker_s: marker::PhantomData,
}
}
}
}
#[cfg(feature = "parallel_iter")]
pub struct ReadOptionParIter<'a,T>
where T: Component
{
entities: &'a [(Entity, MaskType)],
storage: Option<&'a T::Storage>,
}
#[cfg(feature = "parallel_iter")]
impl<'a,T> ReadOptionParIter<'a,T>
where T: Component
{
pub fn new(storage: Option<&'a T::Storage>, entities: &'a [(Entity, MaskType)]) -> ReadOptionParIter<'a, T>{
ReadOptionParIter {
entities,
storage,
}
}
}
#[cfg(feature = "parallel_iter")]
impl<'a, T> ParallelIterator for ReadOptionParIter<'a, T>
where
T: Component,
T::Storage: Storage<'a, T> + Send + Sync + 'a,
<T::Storage as Storage<'a, T>>::Get: Send,
{
type Item = Option<<T::Storage as Storage<'a, T>>::Get>;
#[inline]
fn drive_unindexed<C>(self, consumer: C) -> C::Result
where C: UnindexedConsumer<Self::Item>
{
let storage = self.storage;
self.entities.par_iter().filter_map(move |(entity, _)| unsafe{
let storage = storage.unchecked_unwrap();
if entity.guid != usize::MAX {
if storage.contains(entity.guid) {
Some(Some(storage.get(entity.guid)))
}else{
Some(None)
}
}else{
None
}
}).drive_unindexed(consumer)
}
}
#[cfg(feature = "parallel_iter")]
impl<'a, 'r, T> ParOptionStorage<'r> for StorageOption<'a, T, T::Storage, ReadGuardRef<'a, T::Storage>>
where
for<'s> <T as Component>::Storage: Storage<'s, T>,
T: Component,
{
type ParIter = ReadOptionParIter<'r, T>;
fn par_iter(this: Option<&'r Self>) -> Self::ParIter {
let entities = this.map(|this| this.entities).unwrap_or(&[]);
let storage = this.and_then(|this| this.storage.as_deref());
ReadOptionParIter::new(storage, entities)
}
}
unsafe impl<T: Component> SafeIter<'_> for ReadOption<'_, T>
where for<'s> <T as Component>::Storage: Storage<'s, T>,{}
impl<'a, T: Component> UnorderedData<'a> for ReadOption<'a,T>
where for<'s> <T as Component>::Storage: Storage<'s, T>
{
type Iter = IterOption<'a,
T,
<T as Component>::Storage,
ReadGuardRef<'a, <T as Component>::Storage>>;
type IterMut = IterOption<'a,
T,
<T as Component>::Storage,
ReadGuardRef<'a, <T as Component>::Storage>>;
type Components = T;
type ComponentsRef = Option<<<T as Component>::Storage as Storage<'a, T>>::Get>;
type Storage = StorageOption<'a,
T,
<T as Component>::Storage,
ReadGuardRef<'a, <T as Component>::Storage>>;
fn query_mask<E: EntitiesStorage>(entities: &E) -> Bitmask {
crate::Bitmask::option(entities.component_mask::<T>())
}
fn into_iter<E: EntitiesStorage>(entities: &'a E) -> Self::Iter {
let storage = unsafe{
<Self as UnorderedData>::storage(entities).unchecked_unwrap()
};
IterOption {
ptr: storage.entities.as_ptr(),
end: unsafe{ storage.entities.as_ptr().add(storage.entities.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 storage = entities.storage::<T>();
let entities = entities.entities_ref();
Some(StorageOption{
entities,
storage,
_marker_t: marker::PhantomData,
_marker_s: marker::PhantomData,
})
}
}
impl<'a, T: Component> DataAccesses for ReadOption<'a, T>
where for<'s> <T as Component>::Storage: Storage<'s, T>
{
fn reads() -> Vec<TypeId>{ vec![TypeId::of::<T>()] }
fn writes() -> Vec<TypeId>{ vec![] }
}