1use alloc::{borrow::Cow, vec::Vec};
2use core::marker::PhantomData;
3
4use crate::{
5 archetype::ArchetypeComponentId,
6 component::{ComponentId, Tick},
7 error::Result,
8 never::Never,
9 prelude::{Bundle, Trigger},
10 query::Access,
11 schedule::{Fallible, Infallible},
12 system::{input::SystemIn, System},
13 world::{unsafe_world_cell::UnsafeWorldCell, DeferredWorld, World},
14};
15
16use super::{IntoSystem, SystemParamValidationError};
17
18pub trait ObserverSystem<E: 'static, B: Bundle, Out = Result>:
20 System<In = Trigger<'static, E, B>, Out = Out> + Send + 'static
21{
22}
23
24impl<E: 'static, B: Bundle, Out, T> ObserverSystem<E, B, Out> for T where
25 T: System<In = Trigger<'static, E, B>, Out = Out> + Send + 'static
26{
27}
28
29#[diagnostic::on_unimplemented(
37 message = "`{Self}` cannot become an `ObserverSystem`",
38 label = "the trait `IntoObserverSystem` is not implemented",
39 note = "for function `ObserverSystem`s, ensure the first argument is a `Trigger<T>` and any subsequent ones are `SystemParam`"
40)]
41pub trait IntoObserverSystem<E: 'static, B: Bundle, M, Out = Result>: Send + 'static {
42 type System: ObserverSystem<E, B, Out>;
44
45 fn into_system(this: Self) -> Self::System;
47}
48
49impl<E, B, M, S, Out> IntoObserverSystem<E, B, (Fallible, M), Out> for S
50where
51 S: IntoSystem<Trigger<'static, E, B>, Out, M> + Send + 'static,
52 S::System: ObserverSystem<E, B, Out>,
53 E: 'static,
54 B: Bundle,
55{
56 type System = S::System;
57
58 fn into_system(this: Self) -> Self::System {
59 IntoSystem::into_system(this)
60 }
61}
62
63impl<E, B, M, S> IntoObserverSystem<E, B, (Infallible, M), Result> for S
64where
65 S: IntoSystem<Trigger<'static, E, B>, (), M> + Send + 'static,
66 S::System: ObserverSystem<E, B, ()>,
67 E: Send + Sync + 'static,
68 B: Bundle,
69{
70 type System = InfallibleObserverWrapper<E, B, S::System, ()>;
71
72 fn into_system(this: Self) -> Self::System {
73 InfallibleObserverWrapper::new(IntoSystem::into_system(this))
74 }
75}
76impl<E, B, M, S> IntoObserverSystem<E, B, (Never, M), Result> for S
77where
78 S: IntoSystem<Trigger<'static, E, B>, Never, M> + Send + 'static,
79 E: Send + Sync + 'static,
80 B: Bundle,
81{
82 type System = InfallibleObserverWrapper<E, B, S::System, Never>;
83
84 fn into_system(this: Self) -> Self::System {
85 InfallibleObserverWrapper::new(IntoSystem::into_system(this))
86 }
87}
88
89pub struct InfallibleObserverWrapper<E, B, S, Out> {
91 observer: S,
92 _marker: PhantomData<(E, B, Out)>,
93}
94
95impl<E, B, S, Out> InfallibleObserverWrapper<E, B, S, Out> {
96 pub fn new(observer: S) -> Self {
98 Self {
99 observer,
100 _marker: PhantomData,
101 }
102 }
103}
104
105impl<E, B, S, Out> System for InfallibleObserverWrapper<E, B, S, Out>
106where
107 S: ObserverSystem<E, B, Out>,
108 E: Send + Sync + 'static,
109 B: Bundle,
110 Out: Send + Sync + 'static,
111{
112 type In = Trigger<'static, E, B>;
113 type Out = Result;
114
115 #[inline]
116 fn name(&self) -> Cow<'static, str> {
117 self.observer.name()
118 }
119
120 #[inline]
121 fn component_access(&self) -> &Access<ComponentId> {
122 self.observer.component_access()
123 }
124
125 #[inline]
126 fn archetype_component_access(&self) -> &Access<ArchetypeComponentId> {
127 self.observer.archetype_component_access()
128 }
129
130 #[inline]
131 fn is_send(&self) -> bool {
132 self.observer.is_send()
133 }
134
135 #[inline]
136 fn is_exclusive(&self) -> bool {
137 self.observer.is_exclusive()
138 }
139
140 #[inline]
141 fn has_deferred(&self) -> bool {
142 self.observer.has_deferred()
143 }
144
145 #[inline]
146 unsafe fn run_unsafe(
147 &mut self,
148 input: SystemIn<'_, Self>,
149 world: UnsafeWorldCell,
150 ) -> Self::Out {
151 self.observer.run_unsafe(input, world);
152 Ok(())
153 }
154
155 #[inline]
156 fn apply_deferred(&mut self, world: &mut World) {
157 self.observer.apply_deferred(world);
158 }
159
160 #[inline]
161 fn queue_deferred(&mut self, world: DeferredWorld) {
162 self.observer.queue_deferred(world);
163 }
164
165 #[inline]
166 unsafe fn validate_param_unsafe(
167 &mut self,
168 world: UnsafeWorldCell,
169 ) -> Result<(), SystemParamValidationError> {
170 self.observer.validate_param_unsafe(world)
171 }
172
173 #[inline]
174 fn initialize(&mut self, world: &mut World) {
175 self.observer.initialize(world);
176 }
177
178 #[inline]
179 fn update_archetype_component_access(&mut self, world: UnsafeWorldCell) {
180 self.observer.update_archetype_component_access(world);
181 }
182
183 #[inline]
184 fn check_change_tick(&mut self, change_tick: Tick) {
185 self.observer.check_change_tick(change_tick);
186 }
187
188 #[inline]
189 fn get_last_run(&self) -> Tick {
190 self.observer.get_last_run()
191 }
192
193 #[inline]
194 fn set_last_run(&mut self, last_run: Tick) {
195 self.observer.set_last_run(last_run);
196 }
197
198 fn default_system_sets(&self) -> Vec<crate::schedule::InternedSystemSet> {
199 self.observer.default_system_sets()
200 }
201}
202
203#[cfg(test)]
204mod tests {
205 use crate::{
206 event::Event,
207 observer::Trigger,
208 system::{In, IntoSystem},
209 world::World,
210 };
211
212 #[derive(Event)]
213 struct TriggerEvent;
214
215 #[test]
216 fn test_piped_observer_systems_no_input() {
217 fn a(_: Trigger<TriggerEvent>) {}
218 fn b() {}
219
220 let mut world = World::new();
221 world.add_observer(a.pipe(b));
222 }
223
224 #[test]
225 fn test_piped_observer_systems_with_inputs() {
226 fn a(_: Trigger<TriggerEvent>) -> u32 {
227 3
228 }
229 fn b(_: In<u32>) {}
230
231 let mut world = World::new();
232 world.add_observer(a.pipe(b));
233 }
234}