use std::{marker, ptr};
use crate::{bitmask::{Bitmask, MaskType}, component::Component, entity::{Entity, EntitiesStorage}, storage::{IntoSendStorage, FastIndexExt, Storage, StorageRef}, sync::StorageWriteGuard};
use super::{DataAccesses, FromComponent, OptionStorageMut, SafeIter, UnorderedData};
#[cfg(feature="parallel_iter")]
use super::ParOptionStorageMut;
use std::ops::{Deref, DerefMut};
use std::usize;
use std::any::TypeId;
#[cfg(feature="parallel_iter")]
use rayon::iter::{IntoParallelRefIterator, ParallelIterator, plumbing::UnindexedConsumer};
use unchecked_unwrap::*;
pub struct WriteOption<'a, T>{
component: Option<&'a mut T>,
}
impl<'a, T: Component> FromComponent<'a, Option<&'a mut T>> for WriteOption<'a, T>{
fn from_component(component: Option<&'a mut T>) -> WriteOption<'a,T>{
WriteOption{
component,
}
}
}
impl<'a, T: Component> Deref for WriteOption<'a, T>{
type Target = Option<&'a mut T>;
fn deref(&self) -> &Option<&'a mut T>{
&self.component
}
}
impl<'a, T: Component> DerefMut for WriteOption<'a, T>{
fn deref_mut(&mut self) -> &mut Option<&'a mut T>{
&mut self.component
}
}
pub struct IterOptionMut<'a, T: Component, BS> {
ptr: *const (Entity, MaskType),
end: *const (Entity, MaskType),
storage: StorageOptionMut<'a, T, BS>,
}
impl<'a, 'r, T, BS> Iterator for IterOptionMut<'a, T, BS>
where
<T as Component>::Storage: Storage<'a, T>,
T: Component,
BS: DerefMut<Target = <T as Component>::Storage>,
{
type Item = Option<<<T as Component>::Storage as Storage<'a,T>>::GetMut>;
#[inline]
fn next(&mut self) -> Option<Self::Item>{
let storage = self.storage.storage.as_mut()?;
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_mut(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 StorageOptionMut<'a, T, BS> {
entities: &'a [(Entity, MaskType)],
storage: Option<BS>,
_marker_t: marker::PhantomData<T>,
}
impl<'a, T, BS> FastIndexExt for StorageOptionMut<'a, T, BS>
where
for<'s> <T as Component>::Storage: Storage<'s, T>,
T: Component,
BS: Deref<Target = <T as Component>::Storage>,
{
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, BS> StorageRef<'r> for StorageOptionMut<'a, T, BS>
where
for<'s> <T as Component>::Storage: Storage<'s, T>,
T: Component,
BS: DerefMut<Target = <T as Component>::Storage>,
{
type Data = WriteOption<'a,T>;
type Component = Option<<<T as Component>::Storage as Storage<'r,T>>::GetMut>;
unsafe fn get_fast_unchecked(&mut self, idx: Option<usize>) -> Self::Component {
idx.and_then(|idx| self.storage.as_mut().map(|s| s.fast_get_mut(idx)))
}
#[allow(non_snake_case)]
unsafe fn get_unchecked(&mut self, guid: usize) -> Self::Component{
let storage = self.storage.as_mut()?;
if storage.contains(guid) {
Some(storage.get_mut(guid))
}else{
None
}
}
fn contains(&self, _guid: usize) -> bool{
true
}
}
impl<'a, 'r, T, BS> IntoSendStorage<'r> for StorageOptionMut<'a, T, BS>
where
for<'s> <T as Component>::Storage: Storage<'s, T>,
T: Component,
BS: DerefMut<Target = <T as Component>::Storage>,
{
type SendStorage = StorageOptionMut<'a, T, &'r mut <T as Component>::Storage>;
fn into_send_storage(&'r mut self) -> Self::SendStorage {
StorageOptionMut {
entities: self.entities,
storage: self.storage.as_deref_mut(),
_marker_t: marker::PhantomData,
}
}
}
impl<'a, 'r, T, BS> OptionStorageMut<'r> for StorageOptionMut<'a, T, BS>
where
for<'s> <T as Component>::Storage: Storage<'s, T>,
BS: DerefMut<Target = <T as Component>::Storage>,
T: Component,
{
type IterMut = IterOptionMut<'r, T, &'r mut <T as Component>::Storage>;
fn iter_mut(this: Option<&'r mut Self>) -> Self::IterMut {
let ptr_range = this
.as_ref()
.map(|s| s.entities.as_ptr_range())
.unwrap_or(ptr::null() .. ptr::null());
IterOptionMut{
ptr: ptr_range.start,
end: ptr_range.end,
storage: StorageOptionMut{
entities: this.as_ref().map(|storage| storage.entities).unwrap_or(&[]),
storage: this.and_then(|storage| storage.storage.as_deref_mut()),
_marker_t: marker::PhantomData,
}
}
}
}
#[cfg(feature = "parallel_iter")]
pub struct WriteOptionParIter<'a,T>
where T: Component
{
entities: &'a [(Entity, MaskType)],
storage: Option<&'a mut T::Storage>,
}
#[cfg(feature = "parallel_iter")]
impl<'a, T> WriteOptionParIter<'a, T>
where T: Component
{
pub fn new(storage: Option<&'a mut T::Storage>, entities: &'a [(Entity, MaskType)]) -> WriteOptionParIter<'a, T>{
WriteOptionParIter {
entities,
storage,
}
}
}
#[cfg(feature = "parallel_iter")]
impl<'a, T> ParallelIterator for WriteOptionParIter<'a, T>
where
T: Component,
T::Storage: Storage<'a, T> + Send + Sync + 'a,
<T::Storage as Storage<'a, T>>::GetMut: Send,
{
type Item = Option<<T::Storage as Storage<'a, T>>::GetMut>;
#[inline]
fn drive_unindexed<C>(self, consumer: C) -> C::Result
where C: UnindexedConsumer<Self::Item>
{
let storage = self.storage;
let ids = self.entities;
ids.par_iter().filter_map(move |(entity, _)| unsafe{
let storage = storage.as_ref().unchecked_unwrap();
if entity.guid != usize::MAX {
if storage.contains(entity.guid) {
let storage = storage as *const &mut T::Storage as *mut &mut T::Storage;
Some(Some((*storage).get_mut(entity.guid)))
}else{
Some(None)
}
}else{
None
}
}).drive_unindexed(consumer)
}
}
#[cfg(feature = "parallel_iter")]
impl<'a, 'r, T, BS> ParOptionStorageMut<'r> for StorageOptionMut<'a, T, BS>
where
for<'s> <T as Component>::Storage: Storage<'s, T>,
BS: DerefMut<Target = <T as Component>::Storage>,
T: Component,
{
type ParIterMut = WriteOptionParIter<'r, T>;
fn par_iter_mut(this: Option<&'r mut Self>) -> Self::ParIterMut {
let entities = this.as_ref()
.map(|this| this.entities)
.unwrap_or(&[]);
let storage = this
.and_then(|this| this.storage.as_deref_mut());
WriteOptionParIter::new(storage, entities)
}
}
unsafe impl<T> SafeIter<'_> for WriteOption<'_, T>{}
impl<'a, T: Component> UnorderedData<'a> for WriteOption<'a,T>
where for<'s> <T as Component>::Storage: Storage<'s, T>
{
type Iter = IterOptionMut<'a,
T,
StorageWriteGuard<'a, T>
>;
type IterMut = IterOptionMut<'a,
T,
StorageWriteGuard<'a, T>
>;
type Components = T;
type ComponentsRef = Option<<<T as Component>::Storage as Storage<'a, T>>::GetMut>;
type Storage = StorageOptionMut<'a,
T,
StorageWriteGuard<'a, T>
>;
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()
};
IterOptionMut {
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_mut::<T>();
let entities = entities.entities_ref();
Some(StorageOptionMut{
entities,
storage,
_marker_t: marker::PhantomData,
})
}
}
impl<'a, T: Component> DataAccesses for WriteOption<'a, T>
where for<'s> <T as Component>::Storage: Storage<'s, T>
{
fn reads() -> Vec<TypeId>{ vec![] }
fn writes() -> Vec<TypeId>{ vec![TypeId::of::<T>()] }
}