Skip to main content

bevy_ecs/error/
command_handling.rs

1use crate::{
2    error::BevyError, never::Never, system::entity_command::EntityCommandError,
3    world::error::EntityMutableFetchError,
4};
5use core::fmt::{Debug, Display};
6
7/// A trait implemented for types that can be used as the output of a [`Command`].
8///
9/// [`Command`]: crate::system::Command
10#[diagnostic::on_unimplemented(
11    message = "`{Self}` is not a valid `Command` output type",
12    label = "invalid `Command` output type",
13    note = "the output type of a `Command` should be `()`, `Never`, or a `Result` where the error type can be converted into `BevyError`"
14)]
15pub trait CommandOutput: Sized {
16    /// Converts the output into an optional [`BevyError`].
17    fn to_err(self) -> Option<BevyError>;
18}
19
20impl<T, E> CommandOutput for Result<T, E>
21where
22    E: Into<BevyError>,
23{
24    #[inline]
25    fn to_err(self) -> Option<BevyError> {
26        self.err().map(Into::into)
27    }
28}
29
30impl CommandOutput for Never {
31    #[inline]
32    fn to_err(self) -> Option<BevyError> {
33        None
34    }
35}
36
37impl CommandOutput for () {
38    #[inline]
39    fn to_err(self) -> Option<BevyError> {
40        None
41    }
42}
43
44/// A trait implemented for types that can be used as the output of an [`EntityCommand`].
45///
46/// [`EntityCommand`]: crate::system::EntityCommand
47pub trait EntityCommandOutput {
48    /// The type returned when the command is successfully applied.
49    type Out;
50
51    /// The error type returned when the command fails to apply. The type must
52    /// be convertible into a [`BevyError`] and constructible from an
53    /// [`EntityMutableFetchError`].
54    type Error: Into<BevyError> + From<EntityMutableFetchError>;
55
56    /// Converts the output into a `Result` containing either the successful output or an error.
57    fn into_result(self) -> Result<Self::Out, Self::Error>;
58}
59
60impl EntityCommandOutput for () {
61    type Out = ();
62    type Error = EntityMutableFetchError;
63
64    #[inline]
65    fn into_result(self) -> Result<Self::Out, Self::Error> {
66        Ok(())
67    }
68}
69
70impl<T, E> EntityCommandOutput for Result<T, E>
71where
72    E: Debug + Display + Send + Sync + 'static,
73{
74    type Out = T;
75    type Error = EntityCommandError<E>;
76
77    #[inline]
78    fn into_result(self) -> Result<Self::Out, Self::Error> {
79        self.map_err(EntityCommandError::CommandFailed)
80    }
81}