@@ -365,6 +365,14 @@ impl Error {
365
365
}
366
366
}
367
367
368
+ /// An iterator over the chain of nested errors wrapped by this Error.
369
+ pub fn chain ( & self ) -> impl Iterator < Item = & ( dyn StdError + ' static ) > {
370
+ Chain {
371
+ root : self ,
372
+ current : None ,
373
+ }
374
+ }
375
+
368
376
pub ( crate ) fn bad_self_argument ( to : & str , cause : Error ) -> Self {
369
377
Error :: BadArgument {
370
378
to : Some ( to. to_string ( ) ) ,
@@ -487,3 +495,44 @@ impl serde::de::Error for Error {
487
495
Self :: DeserializeError ( msg. to_string ( ) )
488
496
}
489
497
}
498
+
499
+ struct Chain < ' a > {
500
+ root : & ' a Error ,
501
+ current : Option < & ' a ( dyn StdError + ' static ) > ,
502
+ }
503
+
504
+ impl < ' a > Iterator for Chain < ' a > {
505
+ type Item = & ' a ( dyn StdError + ' static ) ;
506
+
507
+ fn next ( & mut self ) -> Option < Self :: Item > {
508
+ loop {
509
+ let error: Option < & dyn StdError > = match self . current {
510
+ None => {
511
+ self . current = Some ( self . root ) ;
512
+ self . current
513
+ }
514
+ Some ( current) => match current. downcast_ref :: < Error > ( ) ? {
515
+ Error :: BadArgument { cause, .. }
516
+ | Error :: CallbackError { cause, .. }
517
+ | Error :: WithContext { cause, .. } => {
518
+ self . current = Some ( & * * cause) ;
519
+ self . current
520
+ }
521
+ Error :: ExternalError ( err) => {
522
+ self . current = Some ( & * * err) ;
523
+ self . current
524
+ }
525
+ _ => None ,
526
+ } ,
527
+ } ;
528
+
529
+ // Skip `ExternalError` as it only wraps the underlying error
530
+ // without meaningful context
531
+ if let Some ( Error :: ExternalError ( _) ) = error?. downcast_ref :: < Error > ( ) {
532
+ continue ;
533
+ }
534
+
535
+ return self . current ;
536
+ }
537
+ }
538
+ }
0 commit comments