use core::ops::{Deref, DerefMut};
use spin::lock_api::{MappedRwLockWriteGuard, RwLock, RwLockWriteGuard};
use crate::ScriptContext;
pub struct Entity<T> {
data: RwLock<Option<T>>,
default: fn(&ScriptContext) -> T,
}
pub struct EntityRef<'entity, T> {
data: MappedRwLockWriteGuard<'entity, T>,
}
pub struct EntityMut<'entity, T> {
data: MappedRwLockWriteGuard<'entity, T>,
}
impl<T> Entity<T> {
pub const fn new(_name: &'static str, default: fn(&ScriptContext) -> T) -> Self {
Self {
data: RwLock::new(None),
default,
}
}
pub const fn from_string(name: String, default: fn(&ScriptContext) -> T) -> Self {
core::mem::forget(name);
Self {
data: RwLock::new(None),
default,
}
}
pub fn get(&self, context: &ScriptContext) -> EntityRef<'_, T> {
puffin::profile_function!();
let data = RwLockWriteGuard::map(self.data.write(), |data| {
data.get_or_insert_with(|| (self.default)(context))
});
EntityRef { data }
}
pub fn get_mut(&self, context: &ScriptContext) -> EntityMut<'_, T> {
puffin::profile_function!();
let data = RwLockWriteGuard::map(self.data.write(), |data| {
data.get_or_insert_with(|| (self.default)(context))
});
EntityMut { data }
}
}
impl<T> Deref for EntityRef<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl<T> Deref for EntityMut<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl<T> DerefMut for EntityMut<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data
}
}
|