use std::{
borrow::{Borrow, BorrowMut},
marker::PhantomData,
ops::{Deref, DerefMut},
};
use hibitset::BitSet;
use shred::Fetch;
use crate::join::Join;
#[cfg(feature = "parallel")]
use crate::join::ParJoin;
use crate::{
storage::{MaskedStorage, Storage, UnprotectedStorage},
world::{Component, EntitiesRes, Entity, Index},
};
pub enum SequentialRestriction {}
pub enum MutableParallelRestriction {}
pub enum ImmutableParallelRestriction {}
pub trait ImmutableAliasing: Sized {}
impl ImmutableAliasing for SequentialRestriction {}
impl ImmutableAliasing for ImmutableParallelRestriction {}
pub struct RestrictedStorage<'rf, 'st: 'rf, C, S, B, Restrict>
where
C: Component,
S: Borrow<C::Storage> + 'rf,
B: Borrow<BitSet> + 'rf,
{
bitset: B,
data: S,
entities: &'rf Fetch<'st, EntitiesRes>,
phantom: PhantomData<(C, Restrict)>,
}
#[cfg(feature = "parallel")]
unsafe impl<'rf, 'st: 'rf, C, S, B> ParJoin
for &'rf mut RestrictedStorage<'rf, 'st, C, S, B, MutableParallelRestriction>
where
C: Component,
S: BorrowMut<C::Storage> + 'rf,
B: Borrow<BitSet> + 'rf,
{
}
#[cfg(feature = "parallel")]
unsafe impl<'rf, 'st: 'rf, C, S, B, Restrict> ParJoin
for &'rf RestrictedStorage<'rf, 'st, C, S, B, Restrict>
where
C: Component,
S: Borrow<C::Storage> + 'rf,
B: Borrow<BitSet> + 'rf,
Restrict: ImmutableAliasing,
{
}
impl<'rf, 'st: 'rf, C, S, B, Restrict> Join for &'rf RestrictedStorage<'rf, 'st, C, S, B, Restrict>
where
C: Component,
S: Borrow<C::Storage>,
B: Borrow<BitSet>,
{
type Mask = &'rf BitSet;
type Type = PairedStorage<'rf, 'st, C, &'rf C::Storage, &'rf BitSet, Restrict>;
type Value = (&'rf C::Storage, &'rf Fetch<'st, EntitiesRes>, &'rf BitSet);
unsafe fn open(self) -> (Self::Mask, Self::Value) {
let bitset = self.bitset.borrow();
(bitset, (self.data.borrow(), self.entities, bitset))
}
unsafe fn get(value: &mut Self::Value, id: Index) -> Self::Type {
PairedStorage {
index: id,
storage: value.0,
entities: value.1,
bitset: value.2,
phantom: PhantomData,
}
}
}
impl<'rf, 'st: 'rf, C, S, B, Restrict> Join
for &'rf mut RestrictedStorage<'rf, 'st, C, S, B, Restrict>
where
C: Component,
S: BorrowMut<C::Storage>,
B: Borrow<BitSet>,
{
type Mask = &'rf BitSet;
type Type = PairedStorage<'rf, 'st, C, &'rf mut C::Storage, &'rf BitSet, Restrict>;
type Value = (
&'rf mut C::Storage,
&'rf Fetch<'st, EntitiesRes>,
&'rf BitSet,
);
unsafe fn open(self) -> (Self::Mask, Self::Value) {
let bitset = self.bitset.borrow();
(bitset, (self.data.borrow_mut(), self.entities, bitset))
}
unsafe fn get(value: &mut Self::Value, id: Index) -> Self::Type {
let value: &'rf mut Self::Value = &mut *(value as *mut Self::Value);
PairedStorage {
index: id,
storage: value.0,
entities: value.1,
bitset: value.2,
phantom: PhantomData,
}
}
}
impl<'st, T, D> Storage<'st, T, D>
where
T: Component,
D: Deref<Target = MaskedStorage<T>>,
{
pub fn restrict<'rf>(
&'rf self,
) -> RestrictedStorage<'rf, 'st, T, &T::Storage, &BitSet, ImmutableParallelRestriction> {
RestrictedStorage {
bitset: &self.data.mask,
data: &self.data.inner,
entities: &self.entities,
phantom: PhantomData,
}
}
}
impl<'st, T, D> Storage<'st, T, D>
where
T: Component,
D: DerefMut<Target = MaskedStorage<T>>,
{
pub fn restrict_mut<'rf>(
&'rf mut self,
) -> RestrictedStorage<'rf, 'st, T, &mut T::Storage, &BitSet, SequentialRestriction> {
let (mask, data) = self.data.open_mut();
RestrictedStorage {
bitset: mask,
data,
entities: &self.entities,
phantom: PhantomData,
}
}
pub fn par_restrict_mut<'rf>(
&'rf mut self,
) -> RestrictedStorage<'rf, 'st, T, &mut T::Storage, &BitSet, MutableParallelRestriction> {
let (mask, data) = self.data.open_mut();
RestrictedStorage {
bitset: mask,
data,
entities: &self.entities,
phantom: PhantomData,
}
}
}
pub struct PairedStorage<'rf, 'st: 'rf, C, S, B, Restrict> {
index: Index,
storage: S,
bitset: B,
entities: &'rf Fetch<'st, EntitiesRes>,
phantom: PhantomData<(C, Restrict)>,
}
impl<'rf, 'st, C, S, B, Restrict> PairedStorage<'rf, 'st, C, S, B, Restrict>
where
C: Component,
S: Borrow<C::Storage>,
B: Borrow<BitSet>,
{
pub fn get_unchecked(&self) -> &C {
unsafe { self.storage.borrow().get(self.index) }
}
}
impl<'rf, 'st, C, S, B, Restrict> PairedStorage<'rf, 'st, C, S, B, Restrict>
where
C: Component,
S: BorrowMut<C::Storage>,
B: Borrow<BitSet>,
{
pub fn get_mut_unchecked(&mut self) -> &mut C {
unsafe { self.storage.borrow_mut().get_mut(self.index) }
}
}
impl<'rf, 'st, C, S, B, Restrict> PairedStorage<'rf, 'st, C, S, B, Restrict>
where
C: Component,
S: Borrow<C::Storage>,
B: Borrow<BitSet>,
Restrict: ImmutableAliasing,
{
pub fn get(&self, entity: Entity) -> Option<&C> {
if self.bitset.borrow().contains(entity.id()) && self.entities.is_alive(entity) {
Some(unsafe { self.storage.borrow().get(entity.id()) })
} else {
None
}
}
}
impl<'rf, 'st, C, S, B> PairedStorage<'rf, 'st, C, S, B, SequentialRestriction>
where
C: Component,
S: BorrowMut<C::Storage>,
B: Borrow<BitSet>,
{
pub fn get_mut(&mut self, entity: Entity) -> Option<&mut C> {
if self.bitset.borrow().contains(entity.id()) && self.entities.is_alive(entity) {
Some(unsafe { self.storage.borrow_mut().get_mut(entity.id()) })
} else {
None
}
}
}