use std::any::Any; use std::convert::Infallible; use std::fmt::Debug; use crate::component::Sequence as ComponentSequence; use crate::{ComponentStorage, Query}; pub mod stateful; pub trait System: 'static { type Query<'a>; type Input; #[must_use] fn initialize(self, input: Self::Input) -> Self; fn run(&mut self, component_storage: &mut ComponentStorage); fn into_type_erased(self) -> TypeErased; } impl System)> for Func where Func: Fn(Query) + 'static, Comps: ComponentSequence, { type Input = Infallible; type Query<'a> = Query<'a, Comps>; fn initialize(self, _input: Self::Input) -> Self { self } fn run(&mut self, component_storage: &mut ComponentStorage) { self(Query::new(component_storage)); } fn into_type_erased(self) -> TypeErased { TypeErased { data: Box::new(self), func: Box::new(|data, component_storage| { let me = data.downcast_mut::().unwrap(); me.run(component_storage); }), } } } pub trait Into { type System; fn into_system(self) -> Self::System; } pub struct TypeErased { data: Box, func: Box, } impl TypeErased { pub fn run(&mut self, component_storage: &mut ComponentStorage) { (self.func)(self.data.as_mut(), component_storage); } } 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 TypeErasedFunc = dyn Fn(&mut dyn Any, &mut ComponentStorage);