use core::ops::{Deref, DerefMut}; use spin::lock_api::{MappedRwLockWriteGuard, RwLock, RwLockWriteGuard}; use crate::ScriptContext; pub struct Entity { data: RwLock>, default: fn(&ScriptContext) -> T, } pub struct EntityRef<'entity, T> { data: MappedRwLockWriteGuard<'entity, T>, } pub struct EntityMut<'entity, T> { data: MappedRwLockWriteGuard<'entity, T>, } impl Entity { 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 Deref for EntityRef<'_, T> { type Target = T; fn deref(&self) -> &Self::Target { &self.data } } impl Deref for EntityMut<'_, T> { type Target = T; fn deref(&self) -> &Self::Target { &self.data } } impl DerefMut for EntityMut<'_, T> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.data } }