1 // Copyright 2022-present 650 Industries. All rights reserved. 2 3 /** 4 An exception that may have been caused by another error. 5 */ 6 public protocol ChainableException: Error, AnyObject { 7 /** 8 The direct cause of the exception. 9 */ 10 var cause: Error? { get set } 11 12 /** 13 The first error that started the chain of exceptions. 14 */ 15 var rootCause: Error? { get } 16 17 /** 18 Sets the direct cause of the exception and returns itself. 19 */ causedBynull20 func causedBy(_ error: Error?) -> Self 21 22 /** 23 Tells whether any of the cause in chain is of given type. 24 */ 25 func isCausedBy<ErrorType: Error>(_ errorType: ErrorType.Type) -> Bool 26 } 27 28 public extension ChainableException { 29 var rootCause: Error? { 30 if let cause = cause as? ChainableException { 31 return cause.rootCause ?? cause 32 } 33 return cause 34 } 35 36 @discardableResult 37 func causedBy(_ error: Error?) -> Self { 38 cause = error ?? cause 39 return self 40 } 41 42 func isCausedBy<ErrorType: Error>(_ errorType: ErrorType.Type) -> Bool { 43 if cause is ErrorType { 44 return true 45 } 46 if let cause = cause as? ChainableException { 47 return cause.isCausedBy(errorType) 48 } 49 return false 50 } 51 } 52