@@ -45,6 +45,31 @@ pub enum RclrsError {
45
45
}
46
46
}
47
47
48
+ impl RclrsError {
49
+ /// Returns true if the error was due to a timeout, otherwise returns false.
50
+ pub fn is_timeout ( & self ) -> bool {
51
+ matches ! (
52
+ self ,
53
+ RclrsError :: RclError {
54
+ code: RclReturnCode :: Timeout ,
55
+ ..
56
+ }
57
+ )
58
+ }
59
+
60
+ /// Returns true if the error was because a subscription, service, or client
61
+ /// take failed, otherwise returns false.
62
+ pub fn is_take_failed ( & self ) -> bool {
63
+ matches ! (
64
+ self ,
65
+ RclrsError :: RclError {
66
+ code: RclReturnCode :: SubscriptionTakeFailed | RclReturnCode :: ServiceTakeFailed | RclReturnCode :: ClientTakeFailed ,
67
+ ..
68
+ }
69
+ )
70
+ }
71
+ }
72
+
48
73
impl Display for RclrsError {
49
74
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
50
75
match self {
@@ -382,45 +407,79 @@ impl ToResult for rcl_ret_t {
382
407
383
408
/// A helper trait to disregard timeouts as not an error.
384
409
pub trait RclrsErrorFilter {
410
+ /// Get the first error available, or Ok(()) if there are no errors.
411
+ fn first_error ( self ) -> Result < ( ) , RclrsError > ;
412
+
385
413
/// If the result was a timeout error, change it to `Ok(())`.
386
- fn timeout_ok ( self ) -> Result < ( ) , RclrsError > ;
414
+ fn timeout_ok ( self ) -> Self ;
387
415
388
416
/// If a subscription, service, or client take failed, change the result
389
417
/// to be `Ok(())`.
390
- fn take_failed_ok ( self ) -> Result < ( ) , RclrsError > ;
418
+ fn take_failed_ok ( self ) -> Self ;
419
+
420
+ /// Some error types just indicate an early termination but do not indicate
421
+ /// that anything in the system has misbehaved. This filters out anything
422
+ /// that is part of the normal operation of rcl.
423
+ fn ignore_non_errors ( self ) -> Self
424
+ where
425
+ Self : Sized ,
426
+ {
427
+ self
428
+ . timeout_ok ( )
429
+ . take_failed_ok ( )
430
+ }
391
431
}
392
432
393
433
impl RclrsErrorFilter for Result < ( ) , RclrsError > {
434
+ fn first_error ( self ) -> Result < ( ) , RclrsError > {
435
+ self
436
+ }
437
+
394
438
fn timeout_ok ( self ) -> Result < ( ) , RclrsError > {
395
439
match self {
396
440
Ok ( ( ) ) => Ok ( ( ) ) ,
397
441
Err ( err) => {
398
- if matches ! (
399
- err,
400
- RclrsError :: RclError {
401
- code: RclReturnCode :: Timeout ,
402
- ..
403
- }
404
- ) {
405
- return Ok ( ( ) ) ;
442
+ if err. is_timeout ( ) {
443
+ Ok ( ( ) )
444
+ } else {
445
+ Err ( err)
406
446
}
407
-
408
- Err ( err)
409
447
}
410
448
}
411
449
}
412
450
413
451
fn take_failed_ok ( self ) -> Result < ( ) , RclrsError > {
414
452
match self {
415
- Err ( RclrsError :: RclError {
416
- code : RclReturnCode :: SubscriptionTakeFailed | RclReturnCode :: ServiceTakeFailed | RclReturnCode :: ClientTakeFailed ,
417
- ..
418
- } ) => {
419
- // Spurious wakeup - this may happen even when a waitset indicated that
420
- // work was ready, so we won't report it as an error
421
- Ok ( ( ) )
453
+ Err ( err) => {
454
+ if err. is_take_failed ( ) {
455
+ // Spurious wakeup - this may happen even when a waitset indicated that
456
+ // work was ready, so we won't report it as an error
457
+ Ok ( ( ) )
458
+ } else {
459
+ Err ( err)
460
+ }
422
461
}
423
462
other => other,
424
463
}
425
464
}
426
465
}
466
+
467
+ impl RclrsErrorFilter for Vec < RclrsError > {
468
+ fn first_error ( mut self ) -> Result < ( ) , RclrsError > {
469
+ if self . is_empty ( ) {
470
+ return Ok ( ( ) ) ;
471
+ }
472
+
473
+ Err ( self . remove ( 0 ) )
474
+ }
475
+
476
+ fn timeout_ok ( mut self ) -> Self {
477
+ self . retain ( |err| !err. is_timeout ( ) ) ;
478
+ self
479
+ }
480
+
481
+ fn take_failed_ok ( mut self ) -> Self {
482
+ self . retain ( |err| !err. is_take_failed ( ) ) ;
483
+ self
484
+ }
485
+ }
0 commit comments