Path: blob/main/crates/bevy_ecs/src/error/command_handling.rs
6604 views
use core::fmt;12use bevy_utils::prelude::DebugName;34use crate::{5entity::Entity,6never::Never,7system::{entity_command::EntityCommandError, Command, EntityCommand},8world::{error::EntityMutableFetchError, World},9};1011use super::{BevyError, ErrorContext, ErrorHandler};1213/// Takes a [`Command`] that potentially returns a Result and uses a given error handler function to convert it into14/// a [`Command`] that internally handles an error if it occurs and returns `()`.15pub trait HandleError<Out = ()>: Send + 'static {16/// Takes a [`Command`] that returns a Result and uses a given error handler function to convert it into17/// a [`Command`] that internally handles an error if it occurs and returns `()`.18fn handle_error_with(self, error_handler: ErrorHandler) -> impl Command;19/// Takes a [`Command`] that returns a Result and uses the default error handler function to convert it into20/// a [`Command`] that internally handles an error if it occurs and returns `()`.21fn handle_error(self) -> impl Command;22/// Takes a [`Command`] that returns a Result and ignores any error that occurs.23fn ignore_error(self) -> impl Command;24}2526impl<C, T, E> HandleError<Result<T, E>> for C27where28C: Command<Result<T, E>>,29E: Into<BevyError>,30{31fn handle_error_with(self, error_handler: ErrorHandler) -> impl Command {32move |world: &mut World| match self.apply(world) {33Ok(_) => {}34Err(err) => (error_handler)(35err.into(),36ErrorContext::Command {37name: DebugName::type_name::<C>(),38},39),40}41}4243fn handle_error(self) -> impl Command {44move |world: &mut World| match self.apply(world) {45Ok(_) => {}46Err(err) => world.default_error_handler()(47err.into(),48ErrorContext::Command {49name: DebugName::type_name::<C>(),50},51),52}53}5455fn ignore_error(self) -> impl Command {56move |world: &mut World| {57let _ = self.apply(world);58}59}60}6162impl<C> HandleError<Never> for C63where64C: Command<Never>,65{66fn handle_error_with(self, _error_handler: fn(BevyError, ErrorContext)) -> impl Command {67move |world: &mut World| {68self.apply(world);69}70}7172#[inline]73fn handle_error(self) -> impl Command {74move |world: &mut World| {75self.apply(world);76}77}7879#[inline]80fn ignore_error(self) -> impl Command {81move |world: &mut World| {82self.apply(world);83}84}85}8687impl<C> HandleError for C88where89C: Command,90{91#[inline]92fn handle_error_with(self, _error_handler: fn(BevyError, ErrorContext)) -> impl Command {93self94}95#[inline]96fn handle_error(self) -> impl Command {97self98}99#[inline]100fn ignore_error(self) -> impl Command {101self102}103}104105/// Passes in a specific entity to an [`EntityCommand`], resulting in a [`Command`] that106/// internally runs the [`EntityCommand`] on that entity.107///108// NOTE: This is a separate trait from `EntityCommand` because "result-returning entity commands" and109// "non-result returning entity commands" require different implementations, so they cannot be automatically110// implemented. And this isn't the type of implementation that we want to thrust on people implementing111// EntityCommand.112pub trait CommandWithEntity<Out> {113/// Passes in a specific entity to an [`EntityCommand`], resulting in a [`Command`] that114/// internally runs the [`EntityCommand`] on that entity.115fn with_entity(self, entity: Entity) -> impl Command<Out> + HandleError<Out>;116}117118impl<C> CommandWithEntity<Result<(), EntityMutableFetchError>> for C119where120C: EntityCommand,121{122fn with_entity(123self,124entity: Entity,125) -> impl Command<Result<(), EntityMutableFetchError>>126+ HandleError<Result<(), EntityMutableFetchError>> {127move |world: &mut World| -> Result<(), EntityMutableFetchError> {128let entity = world.get_entity_mut(entity)?;129self.apply(entity);130Ok(())131}132}133}134135impl<C, T, Err> CommandWithEntity<Result<T, EntityCommandError<Err>>> for C136where137C: EntityCommand<Result<T, Err>>,138Err: fmt::Debug + fmt::Display + Send + Sync + 'static,139{140fn with_entity(141self,142entity: Entity,143) -> impl Command<Result<T, EntityCommandError<Err>>> + HandleError<Result<T, EntityCommandError<Err>>>144{145move |world: &mut World| {146let entity = world.get_entity_mut(entity)?;147self.apply(entity)148.map_err(EntityCommandError::CommandFailed)149}150}151}152153154