#[cfg(feature="parking_lot")]
use parking_lot::*;
#[cfg(not(feature="parking_lot"))]
use std::sync::RwLockReadGuard;
use sync::ReadGuardRef;
use std::marker;
use ::Component;
use ::ComponentSend;
use ::ComponentThreadLocal;
use ::Bitmask;
use ::NToOneComponent;
use ::NToOneComponentSend;
use ::NToOneComponentThreadLocal;
use entity::{Entities, EntitiesThreadLocal};
use super::{FromComponent, UnorderedData, UnorderedDataLocal};
use storage::{Storage, StorageRef};
#[cfg(feature = "multithreaded")]
use super::ParUnorderedData;
#[cfg(feature = "multithreaded")]
use super::read::ReadStorageParIter;
use std::borrow::Borrow;
use std::ops::Deref;
pub struct ReadRef<'a, T: 'a + NToOneComponent, Ref: 'a + Component>{
_marker: marker::PhantomData<&'a T>,
component: &'a Ref,
}
impl<'a, T: 'a + NToOneComponent, Ref: 'a + Component> FromComponent<'a, &'a Ref> for ReadRef<'a, T, Ref>{
fn from_component(component: &'a Ref) -> ReadRef<'a,T,Ref>{
ReadRef{
component,
_marker: marker::PhantomData
}
}
}
impl<'a, T: 'a + NToOneComponent, Ref: 'a + Component> Deref for ReadRef<'a, T, Ref>{
type Target = Ref;
fn deref(&self) -> &Ref{
self.component
}
}
pub struct StorageReadRef<'a, S, T, SRef, Ref>
where S: Storage<'a,T> + 'a,
T: 'a + NToOneComponentSend,
SRef: Storage<'a,Ref> + 'a,
Ref: 'a + Component
{
storage: RwLockReadGuard<'a, S>,
storage_ref: RwLockReadGuard<'a, SRef>,
_marker: marker::PhantomData<&'a T>,
_marker_ref: marker::PhantomData<&'a Ref>,
}
impl<'a, S, T, SRef, Ref> StorageRef<'a, Option<<SRef as Storage<'a,Ref>>::Get>> for StorageReadRef<'a, S, T, SRef, Ref>
where S: Storage<'a,T> + 'a,
T: 'a + NToOneComponentSend,
SRef: Storage<'a,Ref> + 'a,
Ref: 'a + ComponentSend + Send,
<S as Storage<'a,T>>::Get: Borrow<T>,
{
fn get(&self, guid: usize) -> Option<<SRef as Storage<'a,Ref>>::Get>{
unsafe{
let t = self.storage.get(guid);
if self.storage_ref.contains(t.borrow().guid()) {
let tref = self.storage_ref.get(t.borrow().guid());
Some(tref)
}else{
None
}
}
}
fn contains(&self, guid: usize) -> bool{
self.storage.contains(guid)
}
}
pub struct ReadRefIter<'a, S, SRef, Ref>{
_ids: ::IndexGuard<'a>,
ptr: *const usize,
end: *const usize,
storage: S,
_markersref: marker::PhantomData<SRef>,
_markerref: marker::PhantomData<Ref>,
}
impl<'a, S, SRef, Ref> Iterator for ReadRefIter<'a, S, SRef, Ref>
where S: StorageRef<'a, Option<<SRef as Storage<'a,Ref>>::Get>>,
SRef: Storage<'a,Ref> + 'a,
{
type Item = Option<<SRef as Storage<'a,Ref>>::Get>;
fn next(&mut self) -> Option<Self::Item>{
unsafe {
if self.ptr == self.end {
None
} else {
let guid = *self.ptr;
self.ptr = self.ptr.offset(1);
Some(self.storage.get(guid))
}
}
}
}
impl<'a, T, Ref> UnorderedData<'a> for ReadRef<'a,T,Ref>
where T: 'a + NToOneComponentSend,
Ref: Component + Send,
<<T as Component>::Storage as Storage<'a, T>>::Get: Borrow<T>
{
type Iter = ReadRefIter<'a, Self::Storage, <Ref as Component>::Storage, Ref>;
type Components = Option<Ref>;
type ComponentsRef = Option<<<Ref as Component>::Storage as Storage<'a, Ref>>::Get>;
type Storage = StorageReadRef<'a, <T as Component>::Storage, T, <Ref as Component>::Storage, Ref>;
fn components_mask(entities: Entities<'a>) -> Bitmask {
Bitmask::has(entities.components_mask::<T>())
}
fn into_iter(entities: Entities<'a>) -> Self::Iter{
let ids = entities.entities_for_mask(<Self as UnorderedData>::components_mask(entities));
ReadRefIter{
ptr: ids.index.as_ptr(),
end: unsafe{ ids.index.as_ptr().add(ids.index.len()) },
_ids: ids,
storage: <Self as UnorderedData>::storage(entities),
_markersref: marker::PhantomData,
_markerref: marker::PhantomData,
}
}
fn storage(entities: Entities<'a>) -> Self::Storage{
StorageReadRef{
storage: entities.storage::<T>()
.unwrap_or_else(|| panic!("Trying to use unregistered storage for component {}", T::type_name())),
storage_ref: entities.storage::<Ref>()
.unwrap_or_else(|| panic!("Trying to use unregistered storage for component {}", Ref::type_name())),
_marker: marker::PhantomData,
_marker_ref: marker::PhantomData,
}
}
}
#[cfg(feature = "multithreaded")]
impl<'a, T, Ref> ParUnorderedData<'a> for ReadRef<'a,T,Ref>
where T: 'a + NToOneComponentSend,
Ref: Component + Send,
<<T as Component>::Storage as Storage<'a, T>>::Get: Borrow<T>
{
type ParIter = ReadStorageParIter<'a, Self::ComponentsRef, Self::Storage>;
fn into_pariter(entities: Entities<'a>) -> Self::ParIter{
let ids = entities.entities_for_mask(<Self as UnorderedData>::components_mask(entities));
ReadStorageParIter::new(ids, <Self as UnorderedData>::storage(entities))
}
}
pub struct StorageReadRefLocal<'a, S, T, SRef, Ref>
where S: Storage<'a,T> + 'a,
T: 'a + NToOneComponentThreadLocal,
SRef: Storage<'a,Ref> + 'a,
Ref: 'a + Component
{
storage: ReadGuardRef<'a, S>,
storage_ref: ReadGuardRef<'a, SRef>,
_marker: marker::PhantomData<&'a T>,
_marker_ref: marker::PhantomData<&'a Ref>,
}
impl<'a, S, T, SRef, Ref> StorageRef<'a, Option<<SRef as Storage<'a,Ref>>::Get>> for StorageReadRefLocal<'a, S, T, SRef, Ref>
where S: Storage<'a,T> + 'a,
T: 'a + NToOneComponentThreadLocal,
SRef: Storage<'a, Ref> + 'a,
Ref: 'a + ComponentThreadLocal,
<S as Storage<'a,T>>::Get: Borrow<T>,
{
fn get(&self, guid: usize) -> Option<<SRef as Storage<'a, Ref>>::Get> {
unsafe{
let t = self.storage.get(guid);
if self.storage_ref.contains(t.borrow().guid()){
let tref = self.storage_ref.get(t.borrow().guid());
Some(tref)
}else{
None
}
}
}
fn contains(&self, guid: usize) -> bool{
self.storage.contains(guid)
}
}
impl<'a, T, Ref> UnorderedDataLocal<'a> for ReadRef<'a,T,Ref>
where T: 'a + NToOneComponentThreadLocal,
Ref: Component,
<<T as Component>::Storage as Storage<'a, T>>::Get: Borrow<T>
{
type Iter = ReadRefIter<'a, Self::Storage, <Ref as Component>::Storage, Ref>;
type Components = Option<Ref>;
type ComponentsRef = Option<<<Ref as Component>::Storage as Storage<'a, Ref>>::Get>;
type Storage = StorageReadRefLocal<'a, <T as Component>::Storage, T, <Ref as Component>::Storage, Ref>;
fn components_mask_thread_local(entities: EntitiesThreadLocal<'a>) -> Bitmask {
Bitmask::has(entities.components_mask::<T>())
}
fn into_iter_thread_local(entities: EntitiesThreadLocal<'a>) -> Self::Iter{
let ids = entities.entities_for_mask(<Self as UnorderedDataLocal>::components_mask_thread_local(entities));
ReadRefIter{
ptr: ids.index.as_ptr(),
end: unsafe{ ids.index.as_ptr().add(ids.index.len()) },
_ids: ids,
storage: <Self as UnorderedDataLocal>::storage_thread_local(entities),
_markersref: marker::PhantomData,
_markerref: marker::PhantomData,
}
}
fn storage_thread_local(entities: EntitiesThreadLocal<'a>) -> Self::Storage{
StorageReadRefLocal{
storage: entities.storage_thread_local::<T>()
.unwrap_or_else(|| panic!("Trying to use unregistered storage for component {}", T::type_name())),
storage_ref: entities.storage_thread_local::<Ref>()
.unwrap_or_else(|| panic!("Trying to use unregistered storage for component {}", Ref::type_name())),
_marker: marker::PhantomData,
_marker_ref: marker::PhantomData,
}
}
}