Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/error/command_handling.rs
6604 views
1
use core::fmt;
2
3
use bevy_utils::prelude::DebugName;
4
5
use crate::{
6
entity::Entity,
7
never::Never,
8
system::{entity_command::EntityCommandError, Command, EntityCommand},
9
world::{error::EntityMutableFetchError, World},
10
};
11
12
use super::{BevyError, ErrorContext, ErrorHandler};
13
14
/// Takes a [`Command`] that potentially returns a Result and uses a given error handler function to convert it into
15
/// a [`Command`] that internally handles an error if it occurs and returns `()`.
16
pub trait HandleError<Out = ()>: Send + 'static {
17
/// Takes a [`Command`] that returns a Result and uses a given error handler function to convert it into
18
/// a [`Command`] that internally handles an error if it occurs and returns `()`.
19
fn handle_error_with(self, error_handler: ErrorHandler) -> impl Command;
20
/// Takes a [`Command`] that returns a Result and uses the default error handler function to convert it into
21
/// a [`Command`] that internally handles an error if it occurs and returns `()`.
22
fn handle_error(self) -> impl Command;
23
/// Takes a [`Command`] that returns a Result and ignores any error that occurs.
24
fn ignore_error(self) -> impl Command;
25
}
26
27
impl<C, T, E> HandleError<Result<T, E>> for C
28
where
29
C: Command<Result<T, E>>,
30
E: Into<BevyError>,
31
{
32
fn handle_error_with(self, error_handler: ErrorHandler) -> impl Command {
33
move |world: &mut World| match self.apply(world) {
34
Ok(_) => {}
35
Err(err) => (error_handler)(
36
err.into(),
37
ErrorContext::Command {
38
name: DebugName::type_name::<C>(),
39
},
40
),
41
}
42
}
43
44
fn handle_error(self) -> impl Command {
45
move |world: &mut World| match self.apply(world) {
46
Ok(_) => {}
47
Err(err) => world.default_error_handler()(
48
err.into(),
49
ErrorContext::Command {
50
name: DebugName::type_name::<C>(),
51
},
52
),
53
}
54
}
55
56
fn ignore_error(self) -> impl Command {
57
move |world: &mut World| {
58
let _ = self.apply(world);
59
}
60
}
61
}
62
63
impl<C> HandleError<Never> for C
64
where
65
C: Command<Never>,
66
{
67
fn handle_error_with(self, _error_handler: fn(BevyError, ErrorContext)) -> impl Command {
68
move |world: &mut World| {
69
self.apply(world);
70
}
71
}
72
73
#[inline]
74
fn handle_error(self) -> impl Command {
75
move |world: &mut World| {
76
self.apply(world);
77
}
78
}
79
80
#[inline]
81
fn ignore_error(self) -> impl Command {
82
move |world: &mut World| {
83
self.apply(world);
84
}
85
}
86
}
87
88
impl<C> HandleError for C
89
where
90
C: Command,
91
{
92
#[inline]
93
fn handle_error_with(self, _error_handler: fn(BevyError, ErrorContext)) -> impl Command {
94
self
95
}
96
#[inline]
97
fn handle_error(self) -> impl Command {
98
self
99
}
100
#[inline]
101
fn ignore_error(self) -> impl Command {
102
self
103
}
104
}
105
106
/// Passes in a specific entity to an [`EntityCommand`], resulting in a [`Command`] that
107
/// internally runs the [`EntityCommand`] on that entity.
108
///
109
// NOTE: This is a separate trait from `EntityCommand` because "result-returning entity commands" and
110
// "non-result returning entity commands" require different implementations, so they cannot be automatically
111
// implemented. And this isn't the type of implementation that we want to thrust on people implementing
112
// EntityCommand.
113
pub trait CommandWithEntity<Out> {
114
/// Passes in a specific entity to an [`EntityCommand`], resulting in a [`Command`] that
115
/// internally runs the [`EntityCommand`] on that entity.
116
fn with_entity(self, entity: Entity) -> impl Command<Out> + HandleError<Out>;
117
}
118
119
impl<C> CommandWithEntity<Result<(), EntityMutableFetchError>> for C
120
where
121
C: EntityCommand,
122
{
123
fn with_entity(
124
self,
125
entity: Entity,
126
) -> impl Command<Result<(), EntityMutableFetchError>>
127
+ HandleError<Result<(), EntityMutableFetchError>> {
128
move |world: &mut World| -> Result<(), EntityMutableFetchError> {
129
let entity = world.get_entity_mut(entity)?;
130
self.apply(entity);
131
Ok(())
132
}
133
}
134
}
135
136
impl<C, T, Err> CommandWithEntity<Result<T, EntityCommandError<Err>>> for C
137
where
138
C: EntityCommand<Result<T, Err>>,
139
Err: fmt::Debug + fmt::Display + Send + Sync + 'static,
140
{
141
fn with_entity(
142
self,
143
entity: Entity,
144
) -> impl Command<Result<T, EntityCommandError<Err>>> + HandleError<Result<T, EntityCommandError<Err>>>
145
{
146
move |world: &mut World| {
147
let entity = world.get_entity_mut(entity)?;
148
self.apply(entity)
149
.map_err(EntityCommandError::CommandFailed)
150
}
151
}
152
}
153
154