use std::{ops::Deref, ptr::NonNull, sync::Arc}; use lyra_ecs::{World, Entity}; use parking_lot::{MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}; #[derive(Clone)] pub struct ScriptEntity(pub Entity); impl std::ops::Deref for ScriptEntity { type Target = Entity; fn deref(&self) -> &Self::Target { &self.0 } } #[derive(Clone)] pub struct ScriptWorldPtr(Arc>>); impl ScriptWorldPtr { pub fn read(&self) -> MappedRwLockReadGuard { RwLockReadGuard::map(self.0.read(), |p| unsafe { p.as_ref() }) } pub fn write(&self) -> MappedRwLockWriteGuard { RwLockWriteGuard::map(self.0.write(), |p| unsafe { p.as_mut() }) } } // SAFETY: The inner NonNull pointer is wrapped in an Arc> unsafe impl Send for ScriptWorldPtr {} unsafe impl Sync for ScriptWorldPtr {} #[derive(Clone)] pub struct ScriptWorldPtrGuard(ScriptWorldPtr); impl Deref for ScriptWorldPtrGuard { type Target = ScriptWorldPtr; fn deref(&self) -> &Self::Target { &self.0 } } impl ScriptWorldPtrGuard { /// Creates a new world pointer. /// /// # Safety /// The original `&mut World` must not be used while this guard is created. /// The [World] may only be accessed through this guard or one of its cloned [ScriptWorldPtr]s. #[allow(clippy::arc_with_non_send_sync)] pub unsafe fn new(world: &mut World) -> Self { ScriptWorldPtrGuard(ScriptWorldPtr(Arc::new(RwLock::new(NonNull::from(world))))) } }