use std::any::{Any, type_name}; use std::fmt::Debug; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use std::sync::Arc; use crate::World; use crate::lock::{Lock, WriteGuard}; use crate::system::{Metadata as SystemMetadata, Param as SystemParam}; /// A type which has a single instance and is shared globally. pub trait Sole: Any { fn drop_last(&self) -> bool; fn as_any_mut(&mut self) -> &mut dyn Any; fn as_any(&self) -> &dyn Any; } impl dyn Sole { pub fn downcast_mut(&mut self) -> Option<&mut Real> { self.as_any_mut().downcast_mut() } pub fn downcast_ref(&self) -> Option<&Real> { self.as_any().downcast_ref() } } impl Debug for dyn Sole { fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { formatter.debug_struct("Sole").finish_non_exhaustive() } } /// Holds a reference to a globally shared singleton value. #[derive(Debug)] pub struct Single<'world, SoleT: Sole> { sole: WriteGuard<'world, Box>, _ph: PhantomData, } impl<'world, SoleT> Single<'world, SoleT> where SoleT: Sole, { pub(crate) fn new(sole: &'world Arc>>) -> Self { Self { sole: sole.write_nonblock().unwrap_or_else(|_| { panic!( "Failed to aquire read-write lock to single component {}", type_name::() ) }), _ph: PhantomData, } } } impl<'world, SoleT> SystemParam<'world> for Single<'world, SoleT> where SoleT: Sole, { type Input = (); fn new(world: &'world World, _system_metadata: &SystemMetadata) -> Self { let sole = world.data.sole_storage.get::().unwrap_or_else(|| { panic!("Sole {} was not found in world", type_name::()) }); Self::new(sole) } } impl Deref for Single<'_, SoleT> where SoleT: Sole, { type Target = SoleT; fn deref(&self) -> &Self::Target { self.sole.downcast_ref().unwrap() } } impl DerefMut for Single<'_, SoleT> where SoleT: Sole, { fn deref_mut(&mut self) -> &mut Self::Target { self.sole.downcast_mut().unwrap() } }