1
1
use bevy_utils:: tracing:: warn;
2
2
use core:: fmt:: Debug ;
3
+ use thiserror:: Error ;
3
4
4
5
use crate :: {
5
6
archetype:: ArchetypeComponentId ,
@@ -269,7 +270,7 @@ where
269
270
/// let mut world = World::default();
270
271
/// let entity = world.run_system_once(|mut commands: Commands| {
271
272
/// commands.spawn_empty().id()
272
- /// });
273
+ /// }).unwrap() ;
273
274
/// # assert!(world.get_entity(entity).is_some());
274
275
/// ```
275
276
///
@@ -289,7 +290,7 @@ where
289
290
/// world.spawn(T(1));
290
291
/// let count = world.run_system_once(|query: Query<&T>| {
291
292
/// query.iter().filter(|t| t.0 == 1).count()
292
- /// });
293
+ /// }).unwrap() ;
293
294
///
294
295
/// # assert_eq!(count, 2);
295
296
/// ```
@@ -311,25 +312,25 @@ where
311
312
/// world.spawn(T(0));
312
313
/// world.spawn(T(1));
313
314
/// world.spawn(T(1));
314
- /// let count = world.run_system_once(count);
315
+ /// let count = world.run_system_once(count).unwrap() ;
315
316
///
316
317
/// # assert_eq!(count, 2);
317
318
/// ```
318
319
pub trait RunSystemOnce : Sized {
319
- /// Runs a system and applies its deferred parameters.
320
- fn run_system_once < T , Out , Marker > ( self , system : T ) -> Out
320
+ /// Tries to run a system and apply its deferred parameters.
321
+ fn run_system_once < T , Out , Marker > ( self , system : T ) -> Result < Out , RunSystemError >
321
322
where
322
323
T : IntoSystem < ( ) , Out , Marker > ,
323
324
{
324
325
self . run_system_once_with ( ( ) , system)
325
326
}
326
327
327
- /// Runs a system with given input and applies its deferred parameters.
328
+ /// Tries to run a system with given input and apply deferred parameters.
328
329
fn run_system_once_with < T , In , Out , Marker > (
329
330
self ,
330
331
input : SystemIn < ' _ , T :: System > ,
331
332
system : T ,
332
- ) -> Out
333
+ ) -> Result < Out , RunSystemError >
333
334
where
334
335
T : IntoSystem < In , Out , Marker > ,
335
336
In : SystemInput ;
@@ -340,14 +341,36 @@ impl RunSystemOnce for &mut World {
340
341
self ,
341
342
input : SystemIn < ' _ , T :: System > ,
342
343
system : T ,
343
- ) -> Out
344
+ ) -> Result < Out , RunSystemError >
344
345
where
345
346
T : IntoSystem < In , Out , Marker > ,
346
347
In : SystemInput ,
347
348
{
348
349
let mut system: T :: System = IntoSystem :: into_system ( system) ;
349
350
system. initialize ( self ) ;
350
- system. run ( input, self )
351
+ if system. validate_param ( self ) {
352
+ Ok ( system. run ( input, self ) )
353
+ } else {
354
+ Err ( RunSystemError :: InvalidParams ( system. name ( ) ) )
355
+ }
356
+ }
357
+ }
358
+
359
+ /// Running system failed.
360
+ #[ derive( Error ) ]
361
+ pub enum RunSystemError {
362
+ /// System could not be run due to parameters that failed validation.
363
+ ///
364
+ /// This can occur because the data required by the system was not present in the world.
365
+ #[ error( "The data required by the system {0:?} was not found in the world and the system did not run due to failed parameter validation." ) ]
366
+ InvalidParams ( Cow < ' static , str > ) ,
367
+ }
368
+
369
+ impl Debug for RunSystemError {
370
+ fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
371
+ match self {
372
+ Self :: InvalidParams ( arg0) => f. debug_tuple ( "InvalidParams" ) . field ( arg0) . finish ( ) ,
373
+ }
351
374
}
352
375
}
353
376
@@ -369,7 +392,7 @@ mod tests {
369
392
}
370
393
371
394
let mut world = World :: default ( ) ;
372
- let n = world. run_system_once_with ( 1 , system) ;
395
+ let n = world. run_system_once_with ( 1 , system) . unwrap ( ) ;
373
396
assert_eq ! ( n, 2 ) ;
374
397
assert_eq ! ( world. resource:: <T >( ) . 0 , 1 ) ;
375
398
}
@@ -387,9 +410,9 @@ mod tests {
387
410
let mut world = World :: new ( ) ;
388
411
world. init_resource :: < Counter > ( ) ;
389
412
assert_eq ! ( * world. resource:: <Counter >( ) , Counter ( 0 ) ) ;
390
- world. run_system_once ( count_up) ;
413
+ world. run_system_once ( count_up) . unwrap ( ) ;
391
414
assert_eq ! ( * world. resource:: <Counter >( ) , Counter ( 1 ) ) ;
392
- world. run_system_once ( count_up) ;
415
+ world. run_system_once ( count_up) . unwrap ( ) ;
393
416
assert_eq ! ( * world. resource:: <Counter >( ) , Counter ( 2 ) ) ;
394
417
}
395
418
@@ -402,7 +425,7 @@ mod tests {
402
425
fn command_processing ( ) {
403
426
let mut world = World :: new ( ) ;
404
427
assert_eq ! ( world. entities. len( ) , 0 ) ;
405
- world. run_system_once ( spawn_entity) ;
428
+ world. run_system_once ( spawn_entity) . unwrap ( ) ;
406
429
assert_eq ! ( world. entities. len( ) , 1 ) ;
407
430
}
408
431
@@ -415,7 +438,20 @@ mod tests {
415
438
let mut world = World :: new ( ) ;
416
439
world. insert_non_send_resource ( Counter ( 10 ) ) ;
417
440
assert_eq ! ( * world. non_send_resource:: <Counter >( ) , Counter ( 10 ) ) ;
418
- world. run_system_once ( non_send_count_down) ;
441
+ world. run_system_once ( non_send_count_down) . unwrap ( ) ;
419
442
assert_eq ! ( * world. non_send_resource:: <Counter >( ) , Counter ( 9 ) ) ;
420
443
}
444
+
445
+ #[ test]
446
+ fn run_system_once_invalid_params ( ) {
447
+ struct T ;
448
+ impl Resource for T { }
449
+ fn system ( _: Res < T > ) { }
450
+
451
+ let mut world = World :: default ( ) ;
452
+ // This fails because `T` has not been added to the world yet.
453
+ let result = world. run_system_once ( system) ;
454
+
455
+ assert ! ( matches!( result, Err ( RunSystemError :: InvalidParams ( _) ) ) ) ;
456
+ }
421
457
}
0 commit comments