use std::any::{type_name, Any}; use std::convert::Infallible; use std::fmt::Debug; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use std::panic::{RefUnwindSafe, UnwindSafe}; use ecs_macros::Component; use seq_macro::seq; use crate::component::{ Component, FromOptional as FromOptionalComponent, FromOptionalMut as FromOptionalMutComponent, }; use crate::lock::{ReadGuard, WriteGuard}; use crate::tuple::{ReduceElement as TupleReduceElement, With as TupleWith}; use crate::World; pub mod stateful; pub trait System<'world, Impl>: 'static { type Input; #[must_use] fn initialize(self, input: Self::Input) -> Self; fn run<'this>(&'this self, world: &'world World) where 'this: 'world; fn into_type_erased(self) -> TypeErased; fn get_local_component_mut( &self, ) -> Option>; fn set_local_component( &mut self, local_component: LocalComponent, ); } macro_rules! impl_system { ($c: tt) => { seq!(I in 0..$c { impl<'world, Func, #(TParam~I,)*> System<'world, fn(#(TParam~I,)*)> for Func where Func: Fn(#(TParam~I,)*) + Copy + RefUnwindSafe + UnwindSafe + 'static, #(TParam~I: Param<'world, Flags = NoInitParamFlag>,)* { type Input = Infallible; fn initialize(self, _input: Self::Input) -> Self { self } fn run<'this>(&'this self, world: &'world World) where 'this: 'world { let func = *self; func(#({ TParam~I::new(self, world) },)*); } fn into_type_erased(self) -> TypeErased { TypeErased { data: Box::new(self), run: Box::new(|data, world| { // SAFETY: The caller of TypeErased::run ensures the lifetime // is correct let data = unsafe { &*std::ptr::from_ref(data) }; let me = data .downcast_ref::() .expect("Function downcast failed"); // SAFETY: The caller of TypeErased::run ensures the lifetime // is correct let world = unsafe { &*std::ptr::from_ref(world) }; me.run(world); }), } } fn get_local_component_mut( &self, ) -> Option> { panic!("System does not have any local components"); } fn set_local_component( &mut self, _local_component: LocalComponent, ) { panic!("System does not have any local components"); } } }); }; } seq!(C in 1..16 { impl_system!(C); }); pub trait Into { type System; fn into_system(self) -> Self::System; } pub struct TypeErased { data: Box, run: Box, } impl TypeErased { /// Runs the system. /// /// # Safety /// `world_data` must live at least as long as the [`World`] the system belongs to. pub unsafe fn run(&self, world: &World) { // You have to dereference for downcasting to work for some reason let data = &*self.data; (self.run)(data, world); } } impl Debug for TypeErased { fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { formatter.debug_struct("TypeErased").finish_non_exhaustive() } } /// Function in [`TypeErased`] used to run the system. type TypeErasedRunFn = dyn Fn(&dyn Any, &World) + RefUnwindSafe + UnwindSafe; /// A parameter to a [`System`]. pub unsafe trait Param<'world> { type Input; type Flags; fn initialize( system: &mut impl System<'world, SystemImpl>, input: Self::Input, ); fn new( system: &'world impl System<'world, SystemImpl>, world: &'world World, ) -> Self; } pub struct NoInitParamFlag {} /// A type which can be used as input to a [`System`]. pub trait Input: 'static {} /// Component tuple reducing operation to get the parameters that takes input. pub struct ParamWithInputFilter; impl TupleReduceElement for InputT where Accumulator: TupleWith, { type Return = Accumulator::With; } impl TupleReduceElement for () { type Return = Accumulator; } #[derive(Debug)] pub struct ComponentRefMut<'a, ComponentT: Component> { inner: WriteGuard<'a, Box>, _ph: PhantomData, } impl<'a, ComponentT: Component> ComponentRefMut<'a, ComponentT> { pub(crate) fn new(inner: WriteGuard<'a, Box>) -> Self { Self { inner, _ph: PhantomData } } } impl<'component, ComponentT: Component> FromOptionalMutComponent<'component> for ComponentRefMut<'component, ComponentT> { fn from_optional_mut_component( inner: Option>>, _world: &'component World, ) -> Self { Self { inner: inner.unwrap_or_else(|| { panic!( "Component {} was not found in entity", type_name::() ); }), _ph: PhantomData, } } } impl<'comp, ComponentT> FromOptionalMutComponent<'comp> for Option> where ComponentT: Component, { fn from_optional_mut_component( optional_component: Option>>, _world: &'comp World, ) -> Self { optional_component.map(|component| ComponentRefMut::new(component)) } } impl<'a, ComponentT: Component> Deref for ComponentRefMut<'a, ComponentT> { type Target = ComponentT; fn deref(&self) -> &Self::Target { self.inner.downcast_ref().unwrap() } } impl<'a, ComponentT: Component> DerefMut for ComponentRefMut<'a, ComponentT> { fn deref_mut(&mut self) -> &mut Self::Target { self.inner.downcast_mut().unwrap() } } #[derive(Debug)] pub struct ComponentRef<'a, ComponentT: Component> { inner: ReadGuard<'a, Box>, _ph: PhantomData, } impl<'a, ComponentT: Component> ComponentRef<'a, ComponentT> { pub(crate) fn new(inner: ReadGuard<'a, Box>) -> Self { Self { inner, _ph: PhantomData } } } impl<'component, ComponentT: Component> FromOptionalComponent<'component> for ComponentRef<'component, ComponentT> { fn from_optional_component( inner: Option>>, _world: &'component World, ) -> Self { Self { inner: inner.unwrap_or_else(|| { panic!( "Component {} was not found in entity", type_name::() ); }), _ph: PhantomData, } } } impl<'comp, ComponentT> FromOptionalComponent<'comp> for Option> where ComponentT: Component, { fn from_optional_component( optional_component: Option>>, _world: &'comp World, ) -> Self { optional_component.map(|component| ComponentRef::new(component)) } } impl<'a, ComponentT: Component> Deref for ComponentRef<'a, ComponentT> { type Target = ComponentT; fn deref(&self) -> &Self::Target { self.inner.downcast_ref().unwrap() } } #[derive(Debug, Component)] pub(crate) struct SystemComponent { pub(crate) system: TypeErased, }