bevy_ecs/system/
observer_system.rs

1use crate::{
2    event::Event,
3    prelude::{Bundle, On},
4    system::System,
5};
6
7use super::IntoSystem;
8
9/// Implemented for [`System`]s that have [`On`] as the first argument.
10pub trait ObserverSystem<E: Event, B: Bundle, Out = ()>:
11    System<In = On<'static, 'static, E, B>, Out = Out> + Send + 'static
12{
13}
14
15impl<E: Event, B: Bundle, Out, T> ObserverSystem<E, B, Out> for T where
16    T: System<In = On<'static, 'static, E, B>, Out = Out> + Send + 'static
17{
18}
19
20/// Implemented for systems that convert into [`ObserverSystem`].
21///
22/// # Usage notes
23///
24/// This trait should only be used as a bound for trait implementations or as an
25/// argument to a function. If an observer system needs to be returned from a
26/// function or stored somewhere, use [`ObserverSystem`] instead of this trait.
27#[diagnostic::on_unimplemented(
28    message = "`{Self}` cannot become an `ObserverSystem`",
29    label = "the trait `IntoObserverSystem` is not implemented",
30    note = "for function `ObserverSystem`s, ensure the first argument is `On<T>` and any subsequent ones are `SystemParam`"
31)]
32pub trait IntoObserverSystem<E: Event, B: Bundle, M, Out = ()>: Send + 'static {
33    /// The type of [`System`] that this instance converts into.
34    type System: ObserverSystem<E, B, Out>;
35
36    /// Turns this value into its corresponding [`System`].
37    fn into_system(this: Self) -> Self::System;
38}
39
40impl<E: Event, B, M, Out, S> IntoObserverSystem<E, B, M, Out> for S
41where
42    S: IntoSystem<On<'static, 'static, E, B>, Out, M> + Send + 'static,
43    S::System: ObserverSystem<E, B, Out>,
44    E: 'static,
45    B: Bundle,
46{
47    type System = S::System;
48
49    fn into_system(this: Self) -> Self::System {
50        IntoSystem::into_system(this)
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use crate::{
57        event::Event,
58        observer::On,
59        system::{In, IntoSystem},
60        world::World,
61    };
62
63    #[derive(Event)]
64    struct TriggerEvent;
65
66    #[test]
67    fn test_piped_observer_systems_no_input() {
68        fn a(_: On<TriggerEvent>) {}
69        fn b() {}
70
71        let mut world = World::new();
72        world.add_observer(a.pipe(b));
73    }
74
75    #[test]
76    fn test_piped_observer_systems_with_inputs() {
77        fn a(_: On<TriggerEvent>) -> u32 {
78            3
79        }
80        fn b(_: In<u32>) {}
81
82        let mut world = World::new();
83        world.add_observer(a.pipe(b));
84    }
85}