//! `Runner` defines what does the actual processing of the action. use std::marker::PhantomData; use bevy::ecs::intern::Interned; use bevy::ecs::schedule::ScheduleLabel; use bevy::prelude::{Schedule, Schedules, World}; pub use cancellation_token::{CancellationId, CancellationToken}; pub use output::Output; mod output; mod cancellation_token; /// The structure that implements [`Runner`] is given [`Output`], /// if the system termination condition is met, return `true` and /// pass the system output to [`Output`]. pub trait Runner { /// Run the system. /// /// If this runner finishes, it must return `true`. /// If it returns `true`, an entity attached this runner will be removed. fn run(&mut self, world: &mut World, token: &CancellationToken) -> bool; } /// The boxed runner. /// /// It is created by [`Action`](crate::prelude::Action). #[repr(transparent)] pub struct BoxedRunner(Option>); impl BoxedRunner { #[inline] pub(crate) fn new(runner: impl Runner + 'static) -> Self { Self(Some(Box::new(runner))) } } impl Runner for BoxedRunner { #[inline(always)] fn run(&mut self, world: &mut World, token: &CancellationToken) -> bool { if let Some(mut runner) = self.0.take() { if runner.run(world, token) { true } else { self.0.replace(runner); false } } else { true } } } #[repr(transparent)] pub(crate) struct BoxedRunners(pub Vec<(BoxedRunner, CancellationToken)>, PhantomData); pub(crate) fn initialize_runner