use unchecked_unwrap::UncheckedUnwrap;
use crate::{IntoSendStorage, Storage, entity::EntitiesStorage, storage::{FastIndexExt, ReadOnlyStorage}, sync::{ReadGuardRef, OrderedIndexGuard}, utils::delete_lifetime_mut};
use std::{marker, ops::Deref};
use crate::Component;
use crate::ComponentSend;
use crate::Bitmask;
use crate::entity::Entity;
use super::{
OrderedData, UnorderedData
};
use crate::storage::{HierarchicalStorage, StorageRef, IntoHierarchicalIter};
use crate::utils::delete_lifetime;
use crate::storage::forest::ForestHierarchicalIter;
use crate::idtree;
pub struct ReadAndParentRef<'a, T, Ref>{
_marker_t: marker::PhantomData<&'a T>,
_marker_ref: marker::PhantomData<Ref>,
}
pub struct ParentStorageReadRef<'a, S, T, Ref, SRef> {
storage: S,
storage_ref: SRef,
_marker_t: marker::PhantomData<&'a T>,
_marker_ref: marker::PhantomData<Ref>,
}
impl<'a, 'r, S, T, Ref, SRef> FastIndexExt for ParentStorageReadRef<'a, S, T, Ref, SRef>
where
T: Component,
S: Deref<Target = T::Storage>,
T::Storage: HierarchicalStorage<'a,T>,
Ref: UnorderedData<'a>,
{
type FastIndex = idtree::NodeId;
type StaticTypeId = (T, Ref::Components);
fn fast_index(&self, guid: usize) -> idtree::NodeId {
unsafe{ self.storage.ordered_fast_index(guid) }
}
}
impl<'a, 'r, S, T, Ref, SRef> StorageRef<'r> for ParentStorageReadRef<'a, S, T, Ref, SRef>
where
T: Component,
S: Deref<Target = T::Storage>,
T::Storage: HierarchicalStorage<'a,T>,
Ref: UnorderedData<'a>,
SRef: StorageRef<'r>,
{
type Data = ReadAndParentRef<'a, T, Ref>;
type Component = (&'r T, Option<SRef::Component>);
unsafe fn get_fast_unchecked(&'r mut self, idx: idtree::NodeId) -> Self::Component {
let storage = &self.storage;
let storage_ref = &mut self.storage_ref;
let node = storage.fast_get_node(idx);
let parent = node.parent().and_then(move |p| {
let guid = storage.guid_for(p.id());
storage_ref.get(&Entity{ guid })
});
let node = delete_lifetime(&node as &T);
(&node, parent)
}
unsafe fn get_unchecked(&'r mut self, guid: usize) -> Self::Component {
let storage = &self.storage;
let storage_ref = &mut self.storage_ref;
let node = storage.get_node(guid);
let parent = node.parent().and_then(move |p| {
let guid = storage.guid_for(p.id());
storage_ref.get(&Entity{ guid })
});
let node = delete_lifetime(&node as &T);
(&node, parent)
}
fn contains(&self, guid: usize) -> bool {
self.storage.contains(guid)
}
}
impl<'a, 'r, T, Ref> IntoSendStorage<'r> for ParentStorageReadRef<'a, ReadGuardRef<'a, T::Storage>, T, Ref, Ref::Storage>
where
T: Component,
T::Storage: HierarchicalStorage<'a,T>,
Ref: UnorderedData<'a>,
Ref::Storage: IntoSendStorage<'r>,
{
type SendStorage = ParentStorageReadRef<'a, &'r T::Storage, T, Ref, <Ref::Storage as IntoSendStorage<'r>>::SendStorage>;
fn into_send_storage(&'r mut self) -> Self::SendStorage {
ParentStorageReadRef{
storage: &self.storage,
storage_ref: self.storage_ref.into_send_storage(),
_marker_t: marker::PhantomData,
_marker_ref: marker::PhantomData,
}
}
}
unsafe impl<'a, S, T, Ref, SRef> ReadOnlyStorage for ParentStorageReadRef<'a, S, T, Ref, SRef>
where SRef: ReadOnlyStorage
{}
pub struct ReadAndParentRefIter<'a, S, T, Ref, SRef>
where
T: Component,
Ref: UnorderedData<'a>,
{
it: Option<ForestHierarchicalIter<'a, T>>,
storage: Option<ParentStorageReadRef<'a, S, T, Ref, SRef>>,
}
impl<'a,S,T,Ref,SRef> Iterator for ReadAndParentRefIter<'a, S, T, Ref, SRef>
where
T: Component,
S: Deref<Target = T::Storage>,
T::Storage: HierarchicalStorage<'a,T>,
Ref: UnorderedData<'a> + 'a,
SRef: StorageRef<'a> + 'a,
{
type Item = (&'a T, Option<SRef::Component>);
fn next(&mut self) -> Option<Self::Item>{
let storage = self.storage.as_mut()?;
let it = unsafe{ self.it.as_mut().unchecked_unwrap() };
it.next().map(|n| {
let n_ref = unsafe{ delete_lifetime(&n as &T) };
let p = n.parent().and_then(|p| unsafe {
let storage_ref = delete_lifetime_mut(&mut storage.storage_ref);
let guid = storage.storage.guid_for(p.id());
storage_ref.get(&Entity{ guid })
});
(n_ref, p)
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.it.as_ref().map(|it| it.size_hint()).unwrap_or((0, None))
}
}
impl<'a, T, Ref> OrderedData<'a> for ReadAndParentRef<'a,T,Ref>
where
for<'b> <T as Component>::Storage: HierarchicalStorage<'b,T>,
for<'b> ReadGuardRef<'b, <T as Component>::Storage>: IntoHierarchicalIter<'b,T>,
T: ComponentSend,
Ref: UnorderedData<'a>,
{
type Iter = ReadAndParentRefIter<'a, ReadGuardRef<'a, T::Storage>, T, Ref, Ref::Storage>;
type Components = T;
type ComponentsRef = (&'a T, Option<<Ref as UnorderedData<'a>>::ComponentsRef>);
type Storage = ParentStorageReadRef<'a, ReadGuardRef<'a, T::Storage>, T, Ref, Ref::Storage>;
fn query_mask<E: EntitiesStorage>(entities: &E) -> Bitmask{
Bitmask::has(entities.component_mask::<T>())
}
fn into_iter<E: EntitiesStorage>(entities: &'a E) -> Self::Iter{
let storage = <Self as OrderedData>::storage(entities);
ReadAndParentRefIter{
it: entities.storage::<T>().map(|s| s.into_hierarchical_iter()),
storage,
}
}
fn storage<E: EntitiesStorage>(entities: &'a E) -> Option<Self::Storage>{
Some(ParentStorageReadRef{
storage: entities.storage::<T>()?,
storage_ref: Ref::storage(entities)?,
_marker_t: marker::PhantomData,
_marker_ref: marker::PhantomData,
})
}
fn ordered_ids<S: FastIndexExt, E: EntitiesStorage>(entities: &'a E, query_mask: Bitmask, unordered_storage: &S) -> OrderedIndexGuard<'a>{
entities.ordered_entities_for::<T,S>(query_mask, unordered_storage)
}
}