use hibitset::BitSetAll;
use super::*;
use crate::join::LendJoin;
use crate::world::Generation;
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) {
Ok(self.entry_inner(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 fn entry_inner<'a>(&'a mut self, id: Index) -> StorageEntry<'a, 'e, T, D> {
if self.data.mask.contains(id) {
StorageEntry::Occupied(OccupiedEntry { id, storage: self })
} else {
StorageEntry::Vacant(VacantEntry { id, storage: self })
}
}
}
pub struct Entries<'a, 'b: 'a, T: 'a, D: 'a>(&'a mut Storage<'b, T, D>);
#[nougat::gat]
unsafe impl<'a, 'b: 'a, T: 'a, D: 'a> LendJoin for Entries<'a, 'b, T, D>
where
T: Component,
D: DerefMut<Target = MaskedStorage<T>>,
{
type Mask = BitSetAll;
type Type<'next> = StorageEntry<'next, '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<'next>(value: &'next mut Self::Value, id: Index) -> Self::Type<'next> {
value.entry_inner(id)
}
#[inline]
fn is_unconstrained() -> bool {
true
}
}
unsafe impl<'a, 'b: 'a, T: 'a, D: 'a> RepeatableLendGet for Entries<'a, 'b, T, D>
where
T: Component,
D: DerefMut<Target = MaskedStorage<T>>,
{
}
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) -> AccessMutReturn<'_, T> {
unsafe { self.storage.data.inner.get_mut(self.id) }
}
pub fn into_mut(self) -> AccessMutReturn<'a, T> {
unsafe { self.storage.data.inner.get_mut(self.id) }
}
pub fn insert(&mut self, mut component: T) -> T {
core::mem::swap(&mut component, self.get_mut().access_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) -> AccessMutReturn<'a, T> {
unsafe { self.storage.not_present_insert(self.id, component) };
unsafe { 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 replace(self, component: T) -> Option<T> {
match self {
StorageEntry::Occupied(mut occupied) => Some(occupied.insert(component)),
StorageEntry::Vacant(vacant) => {
vacant.insert(component);
None
}
}
}
pub fn or_insert(self, component: T) -> AccessMutReturn<'a, T> {
self.or_insert_with(|| component)
}
pub fn or_insert_with<F>(self, default: F) -> AccessMutReturn<'a, T>
where
F: FnOnce() -> T,
{
match self {
StorageEntry::Occupied(occupied) => occupied.into_mut(),
StorageEntry::Vacant(vacant) => vacant.insert(default()),
}
}
}