Skip to main content

bevy_ecs/system/
observer_system.rs

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