1use alloc::borrow::Cow;
2use core::marker::PhantomData;
3
4use crate::{
5 archetype::ArchetypeComponentId,
6 component::{ComponentId, Tick},
7 prelude::World,
8 query::Access,
9 schedule::InternedSystemSet,
10 system::{input::SystemInput, SystemIn},
11 world::unsafe_world_cell::UnsafeWorldCell,
12};
13
14use super::{IntoSystem, ReadOnlySystem, System};
15
16#[diagnostic::on_unimplemented(
87 message = "`{Self}` can not combine systems `{A}` and `{B}`",
88 label = "invalid system combination",
89 note = "the inputs and outputs of `{A}` and `{B}` are not compatible with this combiner"
90)]
91pub trait Combine<A: System, B: System> {
92 type In: SystemInput;
94
95 type Out;
97
98 fn combine(
103 input: <Self::In as SystemInput>::Inner<'_>,
104 a: impl FnOnce(SystemIn<'_, A>) -> A::Out,
105 b: impl FnOnce(SystemIn<'_, B>) -> B::Out,
106 ) -> Self::Out;
107}
108
109pub struct CombinatorSystem<Func, A, B> {
113 _marker: PhantomData<fn() -> Func>,
114 a: A,
115 b: B,
116 name: Cow<'static, str>,
117 component_access: Access<ComponentId>,
118 archetype_component_access: Access<ArchetypeComponentId>,
119}
120
121impl<Func, A, B> CombinatorSystem<Func, A, B> {
122 pub const fn new(a: A, b: B, name: Cow<'static, str>) -> Self {
126 Self {
127 _marker: PhantomData,
128 a,
129 b,
130 name,
131 component_access: Access::new(),
132 archetype_component_access: Access::new(),
133 }
134 }
135}
136
137impl<A, B, Func> System for CombinatorSystem<Func, A, B>
138where
139 Func: Combine<A, B> + 'static,
140 A: System,
141 B: System,
142{
143 type In = Func::In;
144 type Out = Func::Out;
145
146 fn name(&self) -> Cow<'static, str> {
147 self.name.clone()
148 }
149
150 fn component_access(&self) -> &Access<ComponentId> {
151 &self.component_access
152 }
153
154 fn archetype_component_access(&self) -> &Access<ArchetypeComponentId> {
155 &self.archetype_component_access
156 }
157
158 fn is_send(&self) -> bool {
159 self.a.is_send() && self.b.is_send()
160 }
161
162 fn is_exclusive(&self) -> bool {
163 self.a.is_exclusive() || self.b.is_exclusive()
164 }
165
166 fn has_deferred(&self) -> bool {
167 self.a.has_deferred() || self.b.has_deferred()
168 }
169
170 unsafe fn run_unsafe(
171 &mut self,
172 input: SystemIn<'_, Self>,
173 world: UnsafeWorldCell,
174 ) -> Self::Out {
175 Func::combine(
176 input,
177 |input| unsafe { self.a.run_unsafe(input, world) },
184 |input| unsafe { self.b.run_unsafe(input, world) },
186 )
187 }
188
189 fn run(&mut self, input: SystemIn<'_, Self>, world: &mut World) -> Self::Out {
190 let world = world.as_unsafe_world_cell();
191 Func::combine(
192 input,
193 |input| self.a.run(input, unsafe { world.world_mut() }),
197 #[allow(clippy::undocumented_unsafe_blocks)]
198 |input| self.b.run(input, unsafe { world.world_mut() }),
199 )
200 }
201
202 #[inline]
203 fn apply_deferred(&mut self, world: &mut World) {
204 self.a.apply_deferred(world);
205 self.b.apply_deferred(world);
206 }
207
208 #[inline]
209 fn queue_deferred(&mut self, mut world: crate::world::DeferredWorld) {
210 self.a.queue_deferred(world.reborrow());
211 self.b.queue_deferred(world);
212 }
213
214 #[inline]
215 unsafe fn validate_param_unsafe(&mut self, world: UnsafeWorldCell) -> bool {
216 unsafe { self.a.validate_param_unsafe(world) }
218 }
219
220 fn initialize(&mut self, world: &mut World) {
221 self.a.initialize(world);
222 self.b.initialize(world);
223 self.component_access.extend(self.a.component_access());
224 self.component_access.extend(self.b.component_access());
225 }
226
227 fn update_archetype_component_access(&mut self, world: UnsafeWorldCell) {
228 self.a.update_archetype_component_access(world);
229 self.b.update_archetype_component_access(world);
230
231 self.archetype_component_access
232 .extend(self.a.archetype_component_access());
233 self.archetype_component_access
234 .extend(self.b.archetype_component_access());
235 }
236
237 fn check_change_tick(&mut self, change_tick: Tick) {
238 self.a.check_change_tick(change_tick);
239 self.b.check_change_tick(change_tick);
240 }
241
242 fn default_system_sets(&self) -> Vec<InternedSystemSet> {
243 let mut default_sets = self.a.default_system_sets();
244 default_sets.append(&mut self.b.default_system_sets());
245 default_sets
246 }
247
248 fn get_last_run(&self) -> Tick {
249 self.a.get_last_run()
250 }
251
252 fn set_last_run(&mut self, last_run: Tick) {
253 self.a.set_last_run(last_run);
254 self.b.set_last_run(last_run);
255 }
256}
257
258unsafe impl<Func, A, B> ReadOnlySystem for CombinatorSystem<Func, A, B>
260where
261 Func: Combine<A, B> + 'static,
262 A: ReadOnlySystem,
263 B: ReadOnlySystem,
264{
265}
266
267impl<Func, A, B> Clone for CombinatorSystem<Func, A, B>
268where
269 A: Clone,
270 B: Clone,
271{
272 fn clone(&self) -> Self {
274 CombinatorSystem::new(self.a.clone(), self.b.clone(), self.name.clone())
275 }
276}
277
278pub struct IntoPipeSystem<A, B> {
280 a: A,
281 b: B,
282}
283
284impl<A, B> IntoPipeSystem<A, B> {
285 pub const fn new(a: A, b: B) -> Self {
287 Self { a, b }
288 }
289}
290
291#[doc(hidden)]
292pub struct IsPipeSystemMarker;
293
294impl<A, B, IA, OA, IB, OB, MA, MB> IntoSystem<IA, OB, (IsPipeSystemMarker, OA, IB, MA, MB)>
295 for IntoPipeSystem<A, B>
296where
297 IA: SystemInput,
298 A: IntoSystem<IA, OA, MA>,
299 B: IntoSystem<IB, OB, MB>,
300 for<'a> IB: SystemInput<Inner<'a> = OA>,
301{
302 type System = PipeSystem<A::System, B::System>;
303
304 fn into_system(this: Self) -> Self::System {
305 let system_a = IntoSystem::into_system(this.a);
306 let system_b = IntoSystem::into_system(this.b);
307 let name = format!("Pipe({}, {})", system_a.name(), system_b.name());
308 PipeSystem::new(system_a, system_b, Cow::Owned(name))
309 }
310}
311
312pub struct PipeSystem<A, B> {
352 a: A,
353 b: B,
354 name: Cow<'static, str>,
355 component_access: Access<ComponentId>,
356 archetype_component_access: Access<ArchetypeComponentId>,
357}
358
359impl<A, B> PipeSystem<A, B>
360where
361 A: System,
362 B: System,
363 for<'a> B::In: SystemInput<Inner<'a> = A::Out>,
364{
365 pub const fn new(a: A, b: B, name: Cow<'static, str>) -> Self {
367 Self {
368 a,
369 b,
370 name,
371 component_access: Access::new(),
372 archetype_component_access: Access::new(),
373 }
374 }
375}
376
377impl<A, B> System for PipeSystem<A, B>
378where
379 A: System,
380 B: System,
381 for<'a> B::In: SystemInput<Inner<'a> = A::Out>,
382{
383 type In = A::In;
384 type Out = B::Out;
385
386 fn name(&self) -> Cow<'static, str> {
387 self.name.clone()
388 }
389
390 fn component_access(&self) -> &Access<ComponentId> {
391 &self.component_access
392 }
393
394 fn archetype_component_access(&self) -> &Access<ArchetypeComponentId> {
395 &self.archetype_component_access
396 }
397
398 fn is_send(&self) -> bool {
399 self.a.is_send() && self.b.is_send()
400 }
401
402 fn is_exclusive(&self) -> bool {
403 self.a.is_exclusive() || self.b.is_exclusive()
404 }
405
406 fn has_deferred(&self) -> bool {
407 self.a.has_deferred() || self.b.has_deferred()
408 }
409
410 unsafe fn run_unsafe(
411 &mut self,
412 input: SystemIn<'_, Self>,
413 world: UnsafeWorldCell,
414 ) -> Self::Out {
415 let value = self.a.run_unsafe(input, world);
416 self.b.run_unsafe(value, world)
417 }
418
419 fn run(&mut self, input: SystemIn<'_, Self>, world: &mut World) -> Self::Out {
420 let value = self.a.run(input, world);
421 self.b.run(value, world)
422 }
423
424 fn apply_deferred(&mut self, world: &mut World) {
425 self.a.apply_deferred(world);
426 self.b.apply_deferred(world);
427 }
428
429 fn queue_deferred(&mut self, mut world: crate::world::DeferredWorld) {
430 self.a.queue_deferred(world.reborrow());
431 self.b.queue_deferred(world);
432 }
433
434 unsafe fn validate_param_unsafe(&mut self, world: UnsafeWorldCell) -> bool {
435 unsafe { self.a.validate_param_unsafe(world) }
437 }
438
439 fn validate_param(&mut self, world: &World) -> bool {
440 self.a.validate_param(world) && self.b.validate_param(world)
441 }
442
443 fn initialize(&mut self, world: &mut World) {
444 self.a.initialize(world);
445 self.b.initialize(world);
446 self.component_access.extend(self.a.component_access());
447 self.component_access.extend(self.b.component_access());
448 }
449
450 fn update_archetype_component_access(&mut self, world: UnsafeWorldCell) {
451 self.a.update_archetype_component_access(world);
452 self.b.update_archetype_component_access(world);
453
454 self.archetype_component_access
455 .extend(self.a.archetype_component_access());
456 self.archetype_component_access
457 .extend(self.b.archetype_component_access());
458 }
459
460 fn check_change_tick(&mut self, change_tick: Tick) {
461 self.a.check_change_tick(change_tick);
462 self.b.check_change_tick(change_tick);
463 }
464
465 fn default_system_sets(&self) -> Vec<InternedSystemSet> {
466 let mut default_sets = self.a.default_system_sets();
467 default_sets.append(&mut self.b.default_system_sets());
468 default_sets
469 }
470
471 fn get_last_run(&self) -> Tick {
472 self.a.get_last_run()
473 }
474
475 fn set_last_run(&mut self, last_run: Tick) {
476 self.a.set_last_run(last_run);
477 self.b.set_last_run(last_run);
478 }
479}
480
481unsafe impl<A, B> ReadOnlySystem for PipeSystem<A, B>
483where
484 A: ReadOnlySystem,
485 B: ReadOnlySystem,
486 for<'a> B::In: SystemInput<Inner<'a> = A::Out>,
487{
488}