use crate::{ prelude::{Bundle, On}, system::System, }; use super::IntoSystem; /// Implemented for [`System`]s that have [`On`] as the first argument. pub trait ObserverSystem: System, Out = Out> + Send + 'static { } impl ObserverSystem for T where T: System, Out = Out> + Send + 'static { } /// Implemented for systems that convert into [`ObserverSystem`]. /// /// # Usage notes /// /// This trait should only be used as a bound for trait implementations or as an /// argument to a function. If an observer system needs to be returned from a /// function or stored somewhere, use [`ObserverSystem`] instead of this trait. #[diagnostic::on_unimplemented( message = "`{Self}` cannot become an `ObserverSystem`", label = "the trait `IntoObserverSystem` is not implemented", note = "for function `ObserverSystem`s, ensure the first argument is `On` and any subsequent ones are `SystemParam`" )] pub trait IntoObserverSystem: Send + 'static { /// The type of [`System`] that this instance converts into. type System: ObserverSystem; /// Turns this value into its corresponding [`System`]. fn into_system(this: Self) -> Self::System; } impl IntoObserverSystem for S where S: IntoSystem, Out, M> + Send + 'static, S::System: ObserverSystem, E: 'static, B: Bundle, { type System = S::System; fn into_system(this: Self) -> Self::System { IntoSystem::into_system(this) } } #[cfg(test)] mod tests { use crate::{ event::BroadcastEvent, observer::On, system::{In, IntoSystem}, world::World, }; #[derive(BroadcastEvent)] struct TriggerEvent; #[test] fn test_piped_observer_systems_no_input() { fn a(_: On) {} fn b() {} let mut world = World::new(); world.add_observer(a.pipe(b)); } #[test] fn test_piped_observer_systems_with_inputs() { fn a(_: On) -> u32 { 3 } fn b(_: In) {} let mut world = World::new(); world.add_observer(a.pipe(b)); } }