use std::mem::transmute; use std::panic::{RefUnwindSafe, UnwindSafe}; use seq_macro::seq; use crate::component::local::SystemWithLocalComponents; use crate::component::Parts as ComponentParts; use crate::event::Emitted as EmittedEvent; use crate::system::initializable::{Initializable, MaybeInitializableParamTuple}; use crate::system::observer::{ Observe, Observed, Observer, WrapperComponent as ObserverWrapperComponent, }; use crate::system::{Into as IntoSystem, Metadata, Param, System, TypeErased}; use crate::World; /// A stateful system. pub struct Stateful { func: Func, local_components: Vec, } macro_rules! impl_system { ($c: tt) => { seq!(I in 0..$c { impl<'world, Func, #(TParam~I,)*> System<'world, fn(&'world (), #(TParam~I,)*)> for Stateful where Func: Fn(#(TParam~I,)*) + Copy + RefUnwindSafe + UnwindSafe + 'static, #(TParam~I: Param<'world, Input: 'static>,)* { type Callbacks = Callbacks; fn finish(self) -> (TypeErased, Self::Callbacks) { let Self { func, local_components } = self; let callbacks = Callbacks { local_components }; let type_erased = TypeErased { run: Box::new(move |world, metadata| { // SAFETY: The caller of TypeErased::run ensures the lifetime // is correct let world = unsafe { &*std::ptr::from_ref(world) }; func(#({ TParam~I::new(&world, &metadata) },)*); }), }; (type_erased, callbacks) } } impl<'world, Func, #(TParam~I,)*> Initializable<'world, fn(&'world (), #(TParam~I,)*)> for Stateful where Func: Fn(#(TParam~I,)*) + Copy + RefUnwindSafe + UnwindSafe + 'static, #(TParam~I: Param<'world, Input: 'static>,)* (#(TParam~I,)*): MaybeInitializableParamTuple<'world, Self> { type Inputs = < (#(TParam~I,)*) as MaybeInitializableParamTuple<'world, Self> >::Inputs; fn initialize(mut self, inputs: Self::Inputs) -> Self { init_initializable_params::<_, (#(TParam~I,)*)>(&mut self, inputs); self } } impl<'world, Func, #(TParam~I,)*> IntoSystem<'world, fn(#(TParam~I,)*)> for Func where #(TParam~I: Param<'world>,)* Func: Fn(#(TParam~I,)*) + Copy + 'static, { type System = Stateful; fn into_system(self) -> Self::System { Self::System { func: self, local_components: Vec::new(), // TODO: Use Vec::with_capacity } } } }); }; } seq!(C in 1..16 { impl_system!(C); }); impl SystemWithLocalComponents for Stateful { fn add_local_component(&mut self, component_parts: ComponentParts) { self.local_components.push(component_parts); } } #[derive(Debug)] pub struct Callbacks { local_components: Vec, } impl crate::system::Callbacks for Callbacks { fn on_created(&mut self, world: &mut World, metadata: Metadata) { for local_comp_parts in self.local_components.drain(..) { world.add_component(metadata.ent_id, local_comp_parts); } } } fn init_initializable_params<'world, SystemT, Params>( system: &mut SystemT, inputs: Params::Inputs, ) where Params: MaybeInitializableParamTuple<'world, SystemT>, { Params::init_initializable(system, inputs); } macro_rules! impl_observer { ($c: tt) => { seq!(I in 0..$c { impl<'world, ObservedT, Func, #(TParam~I,)*> System< 'world, fn(Observe<'world, ObservedT>, #(TParam~I,)*) > for Stateful where ObservedT: Observed, Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static, #(TParam~I: Param<'world>,)* { type Callbacks = Callbacks; fn finish(self) -> (TypeErased, Callbacks) { unimplemented!(); } } impl<'world, ObservedT, Func, #(TParam~I,)*> Initializable< 'world, fn(Observe<'world, ObservedT>, #(TParam~I,)*) > for Stateful where ObservedT: Observed, Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static, #(TParam~I: Param<'world>,)* (#(TParam~I,)*): MaybeInitializableParamTuple<'world, Self> { type Inputs = < (#(TParam~I,)*) as MaybeInitializableParamTuple<'world, Self> >::Inputs; fn initialize(mut self, inputs: Self::Inputs) -> Self { init_initializable_params::<_, (#(TParam~I,)*)>(&mut self, inputs); self } } impl<'world, ObservedT, Func, #(TParam~I,)*> Observer< 'world, fn(Observe<'world, ObservedT>, #(TParam~I,)*) > for Stateful where ObservedT: Observed, Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static, #(TParam~I: Param<'world>,)* { type ObservedEvents = ObservedT::Events; fn observed_events() -> Self::ObservedEvents { ObservedT::events() } fn finish_observer(self) -> (ObserverWrapperComponent, Callbacks) { let Self { func, local_components } = self; let callbacks = Callbacks { local_components }; let wrapper_comp = ObserverWrapperComponent::new( move |world, metadata, emitted_event| { // SAFETY: The caller of TypeErased::run ensures the lifetime // is correct let world = unsafe { &*std::ptr::from_ref(world) }; // SAFETY: The caller of TypeErased::run ensures the lifetime // is correct let emitted_event = unsafe { transmute::, EmittedEvent<'_>>( emitted_event ) }; func(Observe::new(world, emitted_event), #({ TParam~I::new(world, &metadata) },)*); }, ); (wrapper_comp, callbacks) } } impl<'world, Func, ObservedT, #(TParam~I,)*> IntoSystem< 'world, fn(Observe<'world, ObservedT>, #(TParam~I,)*) > for Func where ObservedT: Observed, #(TParam~I: Param<'world>,)* Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static, { type System = Stateful; fn into_system(self) -> Stateful { Stateful { func: self, local_components: Vec::new(), // TODO: Use Vec::with_capacity } } } }); }; } seq!(C in 1..16 { impl_observer!(C); });