use hibitset::BitSetAll;
use super::*;
use crate::join::Join;
impl<'e, T, D> Storage<'e, T, D>
where
T: Component,
D: DerefMut<Target = MaskedStorage<T>>,
{
pub fn entry<'a>(&'a mut self, e: Entity) -> Result<StorageEntry<'a, 'e, T, D>, WrongGeneration>
where
'e: 'a,
{
if self.entities.is_alive(e) {
unsafe {
let entries = self.entries();
let (_, mut value): (BitSetAll, _) = entries.open();
Ok(Entries::get(&mut value, e.id()))
}
} else {
let gen = self
.entities
.alloc
.generation(e.id())
.unwrap_or_else(Generation::one);
Err(WrongGeneration {
action: "attempting to get an entry to a storage",
actual_gen: gen,
entity: e,
})
}
}
pub fn entries<'a>(&'a mut self) -> Entries<'a, 'e, T, D> {
Entries(self)
}
}
pub struct Entries<'a, 'b: 'a, T: 'a, D: 'a>(&'a mut Storage<'b, T, D>);
impl<'a, 'b: 'a, T: 'a, D: 'a> Join for Entries<'a, 'b, T, D>
where
T: Component,
D: Deref<Target = MaskedStorage<T>>,
{
type Mask = BitSetAll;
type Type = StorageEntry<'a, 'b, T, D>;
type Value = &'a mut Storage<'b, T, D>;
unsafe fn open(self) -> (Self::Mask, Self::Value) {
(BitSetAll, self.0)
}
unsafe fn get(value: &mut Self::Value, id: Index) -> Self::Type {
let storage: *mut Storage<'b, T, D> = *value as *mut Storage<'b, T, D>;
if (*storage).data.mask.contains(id) {
StorageEntry::Occupied(OccupiedEntry {
id,
storage: &mut *storage,
})
} else {
StorageEntry::Vacant(VacantEntry {
id,
storage: &mut *storage,
})
}
}
#[inline]
fn is_unconstrained() -> bool {
true
}
}
pub struct OccupiedEntry<'a, 'b: 'a, T: 'a, D: 'a> {
id: Index,
storage: &'a mut Storage<'b, T, D>,
}
impl<'a, 'b, T, D> OccupiedEntry<'a, 'b, T, D>
where
T: Component,
D: Deref<Target = MaskedStorage<T>>,
{
pub fn get(&self) -> &T {
unsafe { self.storage.data.inner.get(self.id) }
}
}
impl<'a, 'b, T, D> OccupiedEntry<'a, 'b, T, D>
where
T: Component,
D: DerefMut<Target = MaskedStorage<T>>,
{
pub fn get_mut(&mut self) -> &mut T {
unsafe { self.storage.data.inner.get_mut(self.id) }
}
pub fn into_mut(self) -> &'a mut T {
unsafe { self.storage.data.inner.get_mut(self.id) }
}
pub fn insert(&mut self, mut component: T) -> T {
std::mem::swap(&mut component, self.get_mut());
component
}
pub fn remove(self) -> T {
self.storage.data.remove(self.id).unwrap()
}
}
pub struct VacantEntry<'a, 'b: 'a, T: 'a, D: 'a> {
id: Index,
storage: &'a mut Storage<'b, T, D>,
}
impl<'a, 'b, T, D> VacantEntry<'a, 'b, T, D>
where
T: Component,
D: DerefMut<Target = MaskedStorage<T>>,
{
pub fn insert(self, component: T) -> &'a mut T {
self.storage.data.mask.add(self.id);
unsafe {
self.storage.data.inner.insert(self.id, component);
self.storage.data.inner.get_mut(self.id)
}
}
}
pub enum StorageEntry<'a, 'b: 'a, T: 'a, D: 'a> {
Occupied(OccupiedEntry<'a, 'b, T, D>),
Vacant(VacantEntry<'a, 'b, T, D>),
}
impl<'a, 'b, T, D> StorageEntry<'a, 'b, T, D>
where
T: Component,
D: DerefMut<Target = MaskedStorage<T>>,
{
pub fn or_insert(self, component: T) -> &'a mut T {
self.or_insert_with(|| component)
}
pub fn or_insert_with<F>(self, default: F) -> &'a mut T
where
F: FnOnce() -> T,
{
match self {
StorageEntry::Occupied(occupied) => occupied.into_mut(),
StorageEntry::Vacant(vacant) => vacant.insert(default()),
}
}
}