From d5a744b0909c4b2bec397ae4dcd43b56aba355c6 Mon Sep 17 00:00:00 2001 From: HampusM Date: Tue, 19 May 2026 00:12:11 +0200 Subject: feat(ecs): add error handling --- ecs/src/system/observer.rs | 106 ++++++++++++++++----------------------------- ecs/src/system/stateful.rs | 75 ++++++++++++++++++++------------ 2 files changed, 85 insertions(+), 96 deletions(-) (limited to 'ecs/src/system') diff --git a/ecs/src/system/observer.rs b/ecs/src/system/observer.rs index 0472614..6893b0f 100644 --- a/ecs/src/system/observer.rs +++ b/ecs/src/system/observer.rs @@ -1,3 +1,4 @@ +use std::any::type_name; use std::fmt::Debug; use std::marker::PhantomData; use std::mem::transmute; @@ -6,20 +7,22 @@ use std::slice::Iter as SliceIter; use ecs_macros::Component; use seq_macro::seq; +use crate::World; use crate::component::Component; use crate::entity::Handle as EntityHandle; +use crate::error::Error; use crate::event::Emitted as EmittedEvent; use crate::pair::Pair; use crate::system::{ Metadata, NoCallbacks, Param, + ReturnValue as SystemReturnValue, System, TypeErased as TypeErasedSystem, }; use crate::uid::Uid; use crate::util::Array; -use crate::World; pub trait Observed { @@ -154,30 +157,34 @@ impl<'world, ObservedT: Observed> EventMatch<'world, ObservedT> macro_rules! impl_observer { ($c: tt) => { seq!(I in 0..$c { - impl<'world, ObservedT, Func, #(TParam~I,)*> System< + impl<'world, ObservedT, Func, Ret, #(TParam~I,)*> System< 'world, - fn(Observe<'world, ObservedT>, #(TParam~I,)*) + fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret > for Func where ObservedT: Observed, - Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static, + Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + 'static, + Ret: SystemReturnValue, #(TParam~I: Param<'world, Input = ()>,)* { type Callbacks = NoCallbacks; fn finish(self) -> (TypeErasedSystem, NoCallbacks) { - unimplemented!(); + const { + panic!("Observers cannot be used as regular systems"); + } } } - impl<'world, ObservedT, Func, #(TParam~I,)*> Observer< + impl<'world, ObservedT, Func, Ret, #(TParam~I,)*> Observer< 'world, - fn(Observe<'world, ObservedT>, #(TParam~I,)*) + fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret > for Func where ObservedT: Observed, - Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static, + Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + 'static, + Ret: SystemReturnValue, #(TParam~I: Param<'world, Input = ()>,)* { type ObservedEvents = ObservedT::Events; @@ -189,8 +196,10 @@ macro_rules! impl_observer { fn finish_observer(self) -> (WrapperComponent, NoCallbacks) { - let wrapper_comp = WrapperComponent { - run: Box::new(move |world, metadata, emitted_event| { + #[allow(unused)] + + let wrapper_comp = WrapperComponent::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) }; @@ -205,9 +214,10 @@ macro_rules! impl_observer { self(Observe::new(world, emitted_event), #({ TParam~I::new(world, &metadata) - },)*); - }), - }; + },)*).into_result() + }, + type_name::() + ); (wrapper_comp, NoCallbacks) } @@ -216,70 +226,25 @@ macro_rules! impl_observer { }; } -seq!(C in 1..16 { +seq!(C in 0..16 { impl_observer!(C); }); -impl<'world, ObservedT, Func> System<'world, fn(Observe<'world, ObservedT>)> for Func -where - ObservedT: Observed, - Func: Fn(Observe<'world, ObservedT>) + Copy + 'static, -{ - type Callbacks = NoCallbacks; - - fn finish(self) -> (TypeErasedSystem, NoCallbacks) - { - const { - panic!("Observers cannot be used as regular systems"); - } - } -} - -impl<'world, ObservedT, Func> Observer<'world, fn(Observe<'world, ObservedT>)> for Func -where - ObservedT: Observed, - Func: Fn(Observe<'world, ObservedT>) + Copy + 'static, -{ - type ObservedEvents = ObservedT::Events; - - fn observed_events() -> Self::ObservedEvents - { - ObservedT::events() - } - - fn finish_observer(self) -> (WrapperComponent, NoCallbacks) - { - let wrapper_comp = WrapperComponent { - run: Box::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) - }; - - self(Observe::new(world, emitted_event)); - }), - }; - - (wrapper_comp, NoCallbacks) - } -} - #[derive(Component)] pub struct WrapperComponent { run: Box, + name: &'static str, } impl WrapperComponent { - pub fn new(run: impl Fn(&World, Metadata, EmittedEvent<'_>) + 'static) -> Self + pub fn new( + run: impl Fn(&World, Metadata, EmittedEvent<'_>) -> Result<(), Error> + 'static, + name: &'static str, + ) -> Self { - Self { run: Box::new(run) } + Self { run: Box::new(run), name } } /// Runs the observer system. @@ -291,9 +256,14 @@ impl WrapperComponent world: &World, metadata: Metadata, emitted_event: EmittedEvent<'_>, - ) + ) -> Result<(), Error> + { + (self.run)(world, metadata, emitted_event) + } + + pub fn name(&self) -> &'static str { - (self.run)(world, metadata, emitted_event); + self.name } } @@ -307,4 +277,4 @@ impl Debug for WrapperComponent } } -type RunFn = dyn Fn(&World, Metadata, EmittedEvent<'_>); +type RunFn = dyn Fn(&World, Metadata, EmittedEvent<'_>) -> Result<(), Error>; diff --git a/ecs/src/system/stateful.rs b/ecs/src/system/stateful.rs index e74ef31..3e0076a 100644 --- a/ecs/src/system/stateful.rs +++ b/ecs/src/system/stateful.rs @@ -1,10 +1,11 @@ +use std::any::type_name; use std::mem::transmute; -use std::panic::{RefUnwindSafe, UnwindSafe}; use seq_macro::seq; -use crate::component::local::SystemWithLocalComponents; +use crate::World; use crate::component::Parts as ComponentParts; +use crate::component::local::SystemWithLocalComponents; use crate::event::Emitted as EmittedEvent; use crate::system::initializable::{Initializable, MaybeInitializableParamTuple}; use crate::system::observer::{ @@ -13,8 +14,14 @@ use crate::system::observer::{ Observer, WrapperComponent as ObserverWrapperComponent, }; -use crate::system::{Into as IntoSystem, Metadata, Param, System, TypeErased}; -use crate::World; +use crate::system::{ + Into as IntoSystem, + Metadata, + Param, + ReturnValue, + System, + TypeErased, +}; /// A stateful system. pub struct Stateful @@ -26,10 +33,11 @@ pub struct Stateful macro_rules! impl_system { ($c: tt) => { seq!(I in 0..$c { - impl<'world, Func, #(TParam~I,)*> - System<'world, fn(&'world (), #(TParam~I,)*)> for Stateful + impl<'world, Func, Ret, #(TParam~I,)*> + System<'world, fn(#(TParam~I,)*) -> Ret> for Stateful where - Func: Fn(#(TParam~I,)*) + Copy + RefUnwindSafe + UnwindSafe + 'static, + Func: Fn(#(TParam~I,)*) -> Ret + 'static, + Ret: ReturnValue, #(TParam~I: Param<'world, Input: 'static>,)* { type Callbacks = Callbacks; @@ -49,7 +57,10 @@ macro_rules! impl_system { func(#({ TParam~I::new(&world, &metadata) },)*); + + Ok(()) }), + name: type_name::() }; @@ -57,10 +68,11 @@ macro_rules! impl_system { } } - impl<'world, Func, #(TParam~I,)*> - Initializable<'world, fn(&'world (), #(TParam~I,)*)> for Stateful + impl<'world, Func, Ret, #(TParam~I,)*> + Initializable<'world, fn(#(TParam~I,)*) -> Ret> for Stateful where - Func: Fn(#(TParam~I,)*) + Copy + RefUnwindSafe + UnwindSafe + 'static, + Func: Fn(#(TParam~I,)*) -> Ret + 'static, + Ret: ReturnValue, #(TParam~I: Param<'world, Input: 'static>,)* (#(TParam~I,)*): MaybeInitializableParamTuple<'world, Self> { @@ -76,11 +88,12 @@ macro_rules! impl_system { } } - impl<'world, Func, #(TParam~I,)*> IntoSystem<'world, fn(#(TParam~I,)*)> - for Func + impl<'world, Func, Ret, #(TParam~I,)*> + IntoSystem<'world, fn(#(TParam~I,)*) -> Ret> for Func where + Func: Fn(#(TParam~I,)*) -> Ret + 'static, + Ret: ReturnValue, #(TParam~I: Param<'world>,)* - Func: Fn(#(TParam~I,)*) + Copy + 'static, { type System = Stateful; @@ -136,13 +149,14 @@ fn init_initializable_params<'world, SystemT, Params>( macro_rules! impl_observer { ($c: tt) => { seq!(I in 0..$c { - impl<'world, ObservedT, Func, #(TParam~I,)*> System< + impl<'world, ObservedT, Func, Ret, #(TParam~I,)*> System< 'world, - fn(Observe<'world, ObservedT>, #(TParam~I,)*) + fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret > for Stateful where ObservedT: Observed, - Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static, + Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + 'static, + Ret: ReturnValue, #(TParam~I: Param<'world>,)* { type Callbacks = Callbacks; @@ -153,13 +167,14 @@ macro_rules! impl_observer { } } - impl<'world, ObservedT, Func, #(TParam~I,)*> Initializable< + impl<'world, ObservedT, Func, Ret, #(TParam~I,)*> Initializable< 'world, - fn(Observe<'world, ObservedT>, #(TParam~I,)*) + fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret > for Stateful where ObservedT: Observed, - Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static, + Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + 'static, + Ret: ReturnValue, #(TParam~I: Param<'world>,)* (#(TParam~I,)*): MaybeInitializableParamTuple<'world, Self> { @@ -175,13 +190,14 @@ macro_rules! impl_observer { } } - impl<'world, ObservedT, Func, #(TParam~I,)*> Observer< + impl<'world, ObservedT, Func, Ret, #(TParam~I,)*> Observer< 'world, - fn(Observe<'world, ObservedT>, #(TParam~I,)*) + fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret > for Stateful where ObservedT: Observed, - Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static, + Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + 'static, + Ret: ReturnValue, #(TParam~I: Param<'world>,)* { type ObservedEvents = ObservedT::Events; @@ -193,6 +209,8 @@ macro_rules! impl_observer { fn finish_observer(self) -> (ObserverWrapperComponent, Callbacks) { + #![allow(unused)] + let Self { func, local_components } = self; let callbacks = Callbacks { local_components }; @@ -213,23 +231,24 @@ macro_rules! impl_observer { func(Observe::new(world, emitted_event), #({ TParam~I::new(world, &metadata) - },)*); + },)*).into_result() }, + type_name::() ); (wrapper_comp, callbacks) } } - impl<'world, Func, ObservedT, #(TParam~I,)*> IntoSystem< + impl<'world, Func, Ret, ObservedT, #(TParam~I,)*> IntoSystem< 'world, - fn(Observe<'world, ObservedT>, - #(TParam~I,)*) + fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret > for Func where ObservedT: Observed, + Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + 'static, + Ret: ReturnValue, #(TParam~I: Param<'world>,)* - Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static, { type System = Stateful; @@ -245,6 +264,6 @@ macro_rules! impl_observer { }; } -seq!(C in 1..16 { +seq!(C in 0..16 { impl_observer!(C); }); -- cgit v1.2.3-18-g5258