github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/exceptions/inner.go (about)

     1  package exceptions
     2  
     3  import "github.com/sagernet/sing/common"
     4  
     5  type HasInnerError interface {
     6  	Unwrap() error
     7  }
     8  
     9  func Unwrap(err error) error {
    10  	for {
    11  		inner, ok := err.(HasInnerError)
    12  		if !ok {
    13  			break
    14  		}
    15  		innerErr := inner.Unwrap()
    16  		if innerErr == nil {
    17  			break
    18  		}
    19  		err = innerErr
    20  	}
    21  	return err
    22  }
    23  
    24  func Cast[T any](err error) (T, bool) {
    25  	if err == nil {
    26  		return common.DefaultValue[T](), false
    27  	}
    28  
    29  	for {
    30  		interfaceError, isInterface := err.(T)
    31  		if isInterface {
    32  			return interfaceError, true
    33  		}
    34  		switch x := err.(type) {
    35  		case interface{ Unwrap() error }:
    36  			err = x.Unwrap()
    37  			if err == nil {
    38  				return common.DefaultValue[T](), false
    39  			}
    40  		case interface{ Unwrap() []error }:
    41  			for _, innerErr := range x.Unwrap() {
    42  				if interfaceError, isInterface = Cast[T](innerErr); isInterface {
    43  					return interfaceError, true
    44  				}
    45  			}
    46  			return common.DefaultValue[T](), false
    47  		default:
    48  			return common.DefaultValue[T](), false
    49  		}
    50  	}
    51  }