use std::panic::{RefUnwindSafe, UnwindSafe}; use seq_macro::seq; use crate::component::local::SystemWithLocalComponents; use crate::component::Parts as ComponentParts; use crate::system::initializable::{Initializable, MaybeInitializableParamTuple}; 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 run<'this>(&'this self, world: &'world World, metadata: Metadata) where 'this: 'world { let func = self.func; func(#({ TParam~I::new(&world, &metadata) },)*); } 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 IntoSystem for Func where 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); }