Skip to content

Commit ce252f8

Browse files
authored
Reorganize system modules (#8419)
# Objective Follow-up to #8377. As the system module has been refactored, there are many types that no longer make sense to live in the files that they do: - The `IntoSystem` trait is in `function_system.rs`, even though this trait is relevant to all kinds of systems. Same for the `In<T>` type. - `PipeSystem` is now just an implementation of `CombinatorSystem`, so `system_piping.rs` no longer needs its own file. ## Solution - Move `IntoSystem`, `In<T>`, and system piping combinators & tests into the top-level `mod.rs` file for `bevy_ecs::system`. - Move `PipeSystem` into `combinator.rs`.
1 parent 764961b commit ce252f8

File tree

4 files changed

+455
-464
lines changed

4 files changed

+455
-464
lines changed

crates/bevy_ecs/src/system/combinator.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,3 +237,65 @@ where
237237
B: ReadOnlySystem,
238238
{
239239
}
240+
241+
/// A [`System`] created by piping the output of the first system into the input of the second.
242+
///
243+
/// This can be repeated indefinitely, but system pipes cannot branch: the output is consumed by the receiving system.
244+
///
245+
/// Given two systems `A` and `B`, A may be piped into `B` as `A.pipe(B)` if the output type of `A` is
246+
/// equal to the input type of `B`.
247+
///
248+
/// Note that for [`FunctionSystem`](crate::system::FunctionSystem)s the output is the return value
249+
/// of the function and the input is the first [`SystemParam`](crate::system::SystemParam) if it is
250+
/// tagged with [`In`](crate::system::In) or `()` if the function has no designated input parameter.
251+
///
252+
/// # Examples
253+
///
254+
/// ```
255+
/// use std::num::ParseIntError;
256+
///
257+
/// use bevy_ecs::prelude::*;
258+
///
259+
/// fn main() {
260+
/// let mut world = World::default();
261+
/// world.insert_resource(Message("42".to_string()));
262+
///
263+
/// // pipe the `parse_message_system`'s output into the `filter_system`s input
264+
/// let mut piped_system = parse_message_system.pipe(filter_system);
265+
/// piped_system.initialize(&mut world);
266+
/// assert_eq!(piped_system.run((), &mut world), Some(42));
267+
/// }
268+
///
269+
/// #[derive(Resource)]
270+
/// struct Message(String);
271+
///
272+
/// fn parse_message_system(message: Res<Message>) -> Result<usize, ParseIntError> {
273+
/// message.0.parse::<usize>()
274+
/// }
275+
///
276+
/// fn filter_system(In(result): In<Result<usize, ParseIntError>>) -> Option<usize> {
277+
/// result.ok().filter(|&n| n < 100)
278+
/// }
279+
/// ```
280+
pub type PipeSystem<SystemA, SystemB> = CombinatorSystem<Pipe, SystemA, SystemB>;
281+
282+
#[doc(hidden)]
283+
pub struct Pipe;
284+
285+
impl<A, B> Combine<A, B> for Pipe
286+
where
287+
A: System,
288+
B: System<In = A::Out>,
289+
{
290+
type In = A::In;
291+
type Out = B::Out;
292+
293+
fn combine(
294+
input: Self::In,
295+
a: impl FnOnce(A::In) -> A::Out,
296+
b: impl FnOnce(B::In) -> B::Out,
297+
) -> Self::Out {
298+
let value = a(input);
299+
b(value)
300+
}
301+
}

crates/bevy_ecs/src/system/function_system.rs

Lines changed: 1 addition & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
use bevy_utils::all_tuples;
1111
use std::{any::TypeId, borrow::Cow, marker::PhantomData};
1212

13-
use super::{PipeSystem, ReadOnlySystem};
13+
use super::{In, IntoSystem, ReadOnlySystem};
1414

1515
/// The metadata of a [`System`].
1616
#[derive(Clone)]
@@ -308,79 +308,6 @@ impl<Param: SystemParam> FromWorld for SystemState<Param> {
308308
}
309309
}
310310

311-
/// Conversion trait to turn something into a [`System`].
312-
///
313-
/// Use this to get a system from a function. Also note that every system implements this trait as
314-
/// well.
315-
///
316-
/// # Examples
317-
///
318-
/// ```
319-
/// use bevy_ecs::prelude::*;
320-
///
321-
/// fn my_system_function(a_usize_local: Local<usize>) {}
322-
///
323-
/// let system = IntoSystem::into_system(my_system_function);
324-
/// ```
325-
// This trait has to be generic because we have potentially overlapping impls, in particular
326-
// because Rust thinks a type could impl multiple different `FnMut` combinations
327-
// even though none can currently
328-
pub trait IntoSystem<In, Out, Marker>: Sized {
329-
type System: System<In = In, Out = Out>;
330-
/// Turns this value into its corresponding [`System`].
331-
fn into_system(this: Self) -> Self::System;
332-
333-
/// Pass the output of this system `A` into a second system `B`, creating a new compound system.
334-
///
335-
/// The second system must have `In<T>` as its first parameter, where `T`
336-
/// is the return type of the first system.
337-
fn pipe<B, Final, MarkerB>(self, system: B) -> PipeSystem<Self::System, B::System>
338-
where
339-
B: IntoSystem<Out, Final, MarkerB>,
340-
{
341-
let system_a = IntoSystem::into_system(self);
342-
let system_b = IntoSystem::into_system(system);
343-
let name = format!("Pipe({}, {})", system_a.name(), system_b.name());
344-
PipeSystem::new(system_a, system_b, Cow::Owned(name))
345-
}
346-
}
347-
348-
// Systems implicitly implement IntoSystem
349-
impl<In, Out, Sys: System<In = In, Out = Out>> IntoSystem<In, Out, ()> for Sys {
350-
type System = Sys;
351-
fn into_system(this: Self) -> Sys {
352-
this
353-
}
354-
}
355-
356-
/// Wrapper type to mark a [`SystemParam`] as an input.
357-
///
358-
/// [`System`]s may take an optional input which they require to be passed to them when they
359-
/// are being [`run`](System::run). For [`FunctionSystems`](FunctionSystem) the input may be marked
360-
/// with this `In` type, but only the first param of a function may be tagged as an input. This also
361-
/// means a system can only have one or zero input parameters.
362-
///
363-
/// # Examples
364-
///
365-
/// Here is a simple example of a system that takes a [`usize`] returning the square of it.
366-
///
367-
/// ```
368-
/// use bevy_ecs::prelude::*;
369-
///
370-
/// fn main() {
371-
/// let mut square_system = IntoSystem::into_system(square);
372-
///
373-
/// let mut world = World::default();
374-
/// square_system.initialize(&mut world);
375-
/// assert_eq!(square_system.run(12, &mut world), 144);
376-
/// }
377-
///
378-
/// fn square(In(input): In<usize>) -> usize {
379-
/// input * input
380-
/// }
381-
/// ```
382-
pub struct In<In>(pub In);
383-
384311
/// The [`System`] counter part of an ordinary function.
385312
///
386313
/// You get this by calling [`IntoSystem::into_system`] on a function that only accepts

0 commit comments

Comments
 (0)