Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Rename system chaining to system piping #6230

Closed
wants to merge 11 commits into from
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -872,10 +872,10 @@ category = "ECS (Entity Component System)"
wasm = false

[[example]]
name = "system_chaining"
path = "examples/ecs/system_chaining.rs"
name = "system_piping"
path = "examples/ecs/system_piping.rs"

[package.metadata.example.system_chaining]
[package.metadata.example.system_piping]
name = "System Chaining"
description = "Chain two systems together, specifying a return type in a system (such as `Result`)"
alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved
category = "ECS (Entity Component System)"
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub mod prelude {
Schedule, Stage, StageLabel, State, SystemLabel, SystemSet, SystemStage,
},
system::{
adapter as system_adapter, Commands, In, IntoChainSystem, IntoSystem, Local, NonSend,
adapter as system_adapter, Commands, In, IntoPipeSystem, IntoSystem, Local, NonSend,
NonSendMut, ParallelCommands, ParamSet, Query, RemovedComponents, Res, ResMut,
Resource, System, SystemParamFunction,
},
Expand Down
16 changes: 8 additions & 8 deletions crates/bevy_ecs/src/schedule/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
RunCriteriaDescriptor, RunCriteriaDescriptorCoercion, RunCriteriaLabel, ShouldRun,
SystemSet,
},
system::{In, IntoChainSystem, Local, Res, ResMut, Resource},
system::{In, IntoPipeSystem, Local, Res, ResMut, Resource},
};
use std::{
any::TypeId,
Expand Down Expand Up @@ -79,7 +79,7 @@ where
(move |state: Res<State<T>>| {
state.stack.last().unwrap() == &pred && state.transition.is_none()
})
.chain(should_run_adapter::<T>)
.pipe(should_run_adapter::<T>)
.after(DriverLabel::of::<T>())
}

Expand All @@ -95,7 +95,7 @@ where
Some(_) => false,
None => *is_inactive,
})
.chain(should_run_adapter::<T>)
.pipe(should_run_adapter::<T>)
.after(DriverLabel::of::<T>())
}

Expand All @@ -118,7 +118,7 @@ where
Some(_) => false,
None => *is_in_stack,
})
.chain(should_run_adapter::<T>)
.pipe(should_run_adapter::<T>)
.after(DriverLabel::of::<T>())
}

Expand All @@ -133,7 +133,7 @@ where
_ => false,
})
})
.chain(should_run_adapter::<T>)
.pipe(should_run_adapter::<T>)
.after(DriverLabel::of::<T>())
}

Expand All @@ -148,7 +148,7 @@ where
_ => false,
})
})
.chain(should_run_adapter::<T>)
.pipe(should_run_adapter::<T>)
.after(DriverLabel::of::<T>())
}

Expand All @@ -162,7 +162,7 @@ where
_ => false,
})
})
.chain(should_run_adapter::<T>)
.pipe(should_run_adapter::<T>)
.after(DriverLabel::of::<T>())
}

Expand All @@ -176,7 +176,7 @@ where
_ => false,
})
})
.chain(should_run_adapter::<T>)
.pipe(should_run_adapter::<T>)
.after(DriverLabel::of::<T>())
}

Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_ecs/src/system/function_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,9 +535,9 @@ impl<T> Copy for SystemTypeIdLabel<T> {}
/// world.insert_resource(Message("42".to_string()));
///
/// // chain the `parse_message_system`'s output into the `filter_system`s input
/// let mut chained_system = IntoSystem::into_system(chain(parse_message, filter));
/// chained_system.initialize(&mut world);
/// assert_eq!(chained_system.run((), &mut world), Some(42));
/// let mut piped_system = IntoSystem::into_system(chain(parse_message, filter));
/// piped_system.initialize(&mut world);
/// assert_eq!(piped_system.run((), &mut world), Some(42));
/// }
///
/// #[derive(Resource)]
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_ecs/src/system/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,17 @@ mod function_system;
mod query;
#[allow(clippy::module_inception)]
mod system;
mod system_chaining;
mod system_param;
mod system_piping;

pub use commands::*;
pub use exclusive_function_system::*;
pub use exclusive_system_param::*;
pub use function_system::*;
pub use query::*;
pub use system::*;
pub use system_chaining::*;
pub use system_param::*;
pub use system_piping::*;

/// Ensure that a given function is a system
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ use crate::{
};
use std::borrow::Cow;

/// A [`System`] that chains two systems together, creating a new system that routes the output of
/// the first system into the input of the second system, yielding the output of the second system.
/// A [`System`] created by piping the output of the first system into the input of the second.
///
/// Given two systems `A` and `B`, A may be chained with `B` as `A.chain(B)` if the output type of `A` is
/// This can be repeated indefinitely, but system pipes cannot branch: the output is consumed by the receiving system.
///
/// Given two systems `A` and `B`, A may be piped into `B` as `A.pipe(B)` if the output type of `A` is
/// equal to the input type of `B`.
///
/// Note that for [`FunctionSystem`](crate::system::FunctionSystem)s the output is the return value
Expand All @@ -28,10 +29,10 @@ use std::borrow::Cow;
/// let mut world = World::default();
/// world.insert_resource(Message("42".to_string()));
///
/// // chain the `parse_message_system`'s output into the `filter_system`s input
/// let mut chained_system = parse_message_system.chain(filter_system);
/// chained_system.initialize(&mut world);
/// assert_eq!(chained_system.run((), &mut world), Some(42));
/// // pipe the `parse_message_system`'s output into the `filter_system`s input
/// let mut piped_system = parse_message_system.pipe(filter_system);
/// piped_system.initialize(&mut world);
/// assert_eq!(piped_system.run((), &mut world), Some(42));
/// }
///
/// #[derive(Resource)]
Expand All @@ -45,15 +46,15 @@ use std::borrow::Cow;
/// result.ok().filter(|&n| n < 100)
/// }
/// ```
pub struct ChainSystem<SystemA, SystemB> {
pub struct PipeSystem<SystemA, SystemB> {
system_a: SystemA,
system_b: SystemB,
name: Cow<'static, str>,
component_access: Access<ComponentId>,
archetype_component_access: Access<ArchetypeComponentId>,
}

impl<SystemA: System, SystemB: System<In = SystemA::Out>> System for ChainSystem<SystemA, SystemB> {
impl<SystemA: System, SystemB: System<In = SystemA::Out>> System for PipeSystem<SystemA, SystemB> {
type In = SystemA::In;
type Out = SystemB::Out;

Expand Down Expand Up @@ -121,33 +122,34 @@ impl<SystemA: System, SystemB: System<In = SystemA::Out>> System for ChainSystem
}
}

/// An extension trait providing the [`IntoChainSystem::chain`] method for convenient [`System`]
/// chaining.
/// An extension trait providing the [`IntoPipeSystem::pipe`] method to pass input from one system into the next.
///
/// The first system must have a non-empty return type `T`
alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved
/// and the second system must have [`In<T>`](crate::system::In) as its first system parameter.
///
/// This trait is blanket implemented for all system pairs that fulfill the chaining requirement.
/// This trait is blanket implemented for all system pairs that fulfill the type requirements.
///
/// See [`ChainSystem`].
pub trait IntoChainSystem<ParamA, Payload, SystemB, ParamB, Out>:
/// See [`PipeSystem`].
pub trait IntoPipeSystem<ParamA, Payload, SystemB, ParamB, Out>:
IntoSystem<(), Payload, ParamA> + Sized
where
SystemB: IntoSystem<Payload, Out, ParamB>,
{
/// Chain this system `A` with another system `B` creating a new system that feeds system A's
/// output into system `B`, returning the output of system `B`.
fn chain(self, system: SystemB) -> ChainSystem<Self::System, SystemB::System>;
/// Pass the output of this system `A` into a second system `B`, creating a new compound system.
fn pipe(self, system: SystemB) -> PipeSystem<Self::System, SystemB::System>;
}

impl<SystemA, ParamA, Payload, SystemB, ParamB, Out>
IntoChainSystem<ParamA, Payload, SystemB, ParamB, Out> for SystemA
IntoPipeSystem<ParamA, Payload, SystemB, ParamB, Out> for SystemA
where
SystemA: IntoSystem<(), Payload, ParamA>,
SystemB: IntoSystem<Payload, Out, ParamB>,
{
fn chain(self, system: SystemB) -> ChainSystem<SystemA::System, SystemB::System> {
fn pipe(self, system: SystemB) -> PipeSystem<SystemA::System, SystemB::System> {
let system_a = IntoSystem::into_system(self);
let system_b = IntoSystem::into_system(system);
ChainSystem {
name: Cow::Owned(format!("Chain({}, {})", system_a.name(), system_b.name())),
PipeSystem {
name: Cow::Owned(format!("Pipe({}, {})", system_a.name(), system_b.name())),
system_a,
system_b,
archetype_component_access: Default::default(),
Expand All @@ -156,7 +158,7 @@ where
}
}

/// A collection of common adapters for [chaining](super::ChainSystem) the result of a system.
/// A collection of common adapters for [piping](super::PipeSystem) the result of a system.
pub mod adapter {
use crate::system::In;
use std::fmt::Debug;
Expand All @@ -168,9 +170,9 @@ pub mod adapter {
/// use bevy_ecs::prelude::*;
///
/// return1
/// .chain(system_adapter::new(u32::try_from))
/// .chain(system_adapter::unwrap)
/// .chain(print);
/// .pipe(system_adapter::new(u32::try_from))
/// .pipe(system_adapter::unwrap)
/// .pipe(print);
///
/// fn return1() -> u64 { 1 }
/// fn print(In(x): In<impl std::fmt::Debug>) {
Expand Down Expand Up @@ -204,7 +206,7 @@ pub mod adapter {
/// .add_system_to_stage(
/// CoreStage::Update,
/// // Panic if the load system returns an error.
/// load_save_system.chain(system_adapter::unwrap)
/// load_save_system.pipe(system_adapter::unwrap)
/// )
/// // ...
/// # ;
Expand All @@ -224,7 +226,7 @@ pub mod adapter {
res.unwrap()
}

/// System adapter that ignores the output of the previous system in a chain.
/// System adapter that ignores the output of the previous system in a pipe.
/// This is useful for fallible systems that should simply return early in case of an `Err`/`None`.
///
/// # Examples
Expand All @@ -248,7 +250,7 @@ pub mod adapter {
/// .add_system_to_stage(
/// CoreStage::Update,
/// // If the system fails, just move on and try again next frame.
/// fallible_system.chain(system_adapter::ignore)
/// fallible_system.pipe(system_adapter::ignore)
/// )
/// // ...
/// # ;
Expand Down Expand Up @@ -278,8 +280,8 @@ pub mod adapter {
unimplemented!()
}

assert_is_system(returning::<Result<u32, std::io::Error>>.chain(unwrap));
assert_is_system(returning::<Option<()>>.chain(ignore));
assert_is_system(returning::<&str>.chain(new(u64::from_str)).chain(unwrap));
assert_is_system(returning::<Result<u32, std::io::Error>>.pipe(unwrap));
assert_is_system(returning::<Option<()>>.pipe(ignore));
assert_is_system(returning::<&str>.pipe(new(u64::from_str)).pipe(unwrap));
}
}
2 changes: 1 addition & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ Example | Description
[Removal Detection](../examples/ecs/removal_detection.rs) | Query for entities that had a specific component removed in a previous stage during the current frame
[Startup System](../examples/ecs/startup_system.rs) | Demonstrates a startup system (one that runs once when the app starts up)
[State](../examples/ecs/state.rs) | Illustrates how to use States to control transitioning from a Menu state to an InGame state
[System Chaining](../examples/ecs/system_chaining.rs) | Chain two systems together, specifying a return type in a system (such as `Result`)
[System Chaining](../examples/ecs/system_piping.rs) | Chain two systems together, specifying a return type in a system (such as `Result`)
[System Closure](../examples/ecs/system_closure.rs) | Show how to use closures as systems, and how to configure `Local` variables by capturing external state
[System Parameter](../examples/ecs/system_param.rs) | Illustrates creating custom system parameters with `SystemParam`
[System Sets](../examples/ecs/system_sets.rs) | Shows `SystemSet` use along with run criterion
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//! Illustrates how to make a single system from multiple functions running in sequence and sharing
//! their inputs and outputs.
//! Illustrates how to make a single system from multiple functions running in sequence,
//! passing the output of the first into the input of the next.

use anyhow::Result;
use bevy::prelude::*;

fn main() {
App::new()
.insert_resource(Message("42".to_string()))
.add_system(parse_message_system.chain(handler_system))
.add_system(parse_message_system.pipe(handler_system))
.run();
}

Expand Down