use crate::{
component::{Component, Mutable},
world::{EntityWorldMut, Mut},
};
use core::marker::PhantomData;
pub enum ComponentEntry<'w, 'a, T: Component> {
Occupied(OccupiedComponentEntry<'w, 'a, T>),
Vacant(VacantComponentEntry<'w, 'a, T>),
}
impl<'w, 'a, T: Component<Mutability = Mutable>> ComponentEntry<'w, 'a, T> {
#[inline]
pub fn and_modify<F: FnOnce(Mut<'_, T>)>(self, f: F) -> Self {
match self {
ComponentEntry::Occupied(mut entry) => {
f(entry.get_mut());
ComponentEntry::Occupied(entry)
}
ComponentEntry::Vacant(entry) => ComponentEntry::Vacant(entry),
}
}
}
impl<'w, 'a, T: Component> ComponentEntry<'w, 'a, T> {
#[inline]
pub fn insert_entry(self, component: T) -> OccupiedComponentEntry<'w, 'a, T> {
match self {
ComponentEntry::Occupied(mut entry) => {
entry.insert(component);
entry
}
ComponentEntry::Vacant(entry) => entry.insert(component),
}
}
#[inline]
pub fn or_insert(self, default: T) -> OccupiedComponentEntry<'w, 'a, T> {
match self {
ComponentEntry::Occupied(entry) => entry,
ComponentEntry::Vacant(entry) => entry.insert(default),
}
}
#[inline]
pub fn or_insert_with<F: FnOnce() -> T>(self, default: F) -> OccupiedComponentEntry<'w, 'a, T> {
match self {
ComponentEntry::Occupied(entry) => entry,
ComponentEntry::Vacant(entry) => entry.insert(default()),
}
}
}
impl<'w, 'a, T: Component + Default> ComponentEntry<'w, 'a, T> {
#[inline]
pub fn or_default(self) -> OccupiedComponentEntry<'w, 'a, T> {
match self {
ComponentEntry::Occupied(entry) => entry,
ComponentEntry::Vacant(entry) => entry.insert(Default::default()),
}
}
}
pub struct OccupiedComponentEntry<'w, 'a, T: Component> {
pub(crate) entity_world: &'a mut EntityWorldMut<'w>,
pub(crate) _marker: PhantomData<T>,
}
impl<'w, 'a, T: Component> OccupiedComponentEntry<'w, 'a, T> {
#[inline]
pub fn get(&self) -> &T {
self.entity_world.get::<T>().unwrap()
}
#[inline]
pub fn insert(&mut self, component: T) {
self.entity_world.insert(component);
}
#[inline]
pub fn take(self) -> T {
self.entity_world.take().unwrap()
}
}
impl<'w, 'a, T: Component<Mutability = Mutable>> OccupiedComponentEntry<'w, 'a, T> {
#[inline]
pub fn get_mut(&mut self) -> Mut<'_, T> {
self.entity_world.get_mut::<T>().unwrap()
}
#[inline]
pub fn into_mut(self) -> Mut<'a, T> {
self.entity_world.get_mut().unwrap()
}
}
pub struct VacantComponentEntry<'w, 'a, T: Component> {
pub(crate) entity_world: &'a mut EntityWorldMut<'w>,
pub(crate) _marker: PhantomData<T>,
}
impl<'w, 'a, T: Component> VacantComponentEntry<'w, 'a, T> {
#[inline]
pub fn insert(self, component: T) -> OccupiedComponentEntry<'w, 'a, T> {
self.entity_world.insert(component);
OccupiedComponentEntry {
entity_world: self.entity_world,
_marker: PhantomData,
}
}
}