github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/exceptions/multi.go (about) 1 package exceptions 2 3 import ( 4 "errors" 5 "strings" 6 7 "github.com/sagernet/sing/common" 8 F "github.com/sagernet/sing/common/format" 9 ) 10 11 type multiError struct { 12 errors []error 13 } 14 15 func (e *multiError) Error() string { 16 return strings.Join(F.MapToString(e.errors), " | ") 17 } 18 19 func (e *multiError) Unwrap() []error { 20 return e.errors 21 } 22 23 func Errors(errors ...error) error { 24 errors = common.FilterNotNil(errors) 25 errors = ExpandAll(errors) 26 errors = common.FilterNotNil(errors) 27 errors = common.UniqBy(errors, error.Error) 28 switch len(errors) { 29 case 0: 30 return nil 31 case 1: 32 return errors[0] 33 } 34 return &multiError{ 35 errors: errors, 36 } 37 } 38 39 func Expand(err error) []error { 40 if err == nil { 41 return nil 42 } else if multiErr, isMultiErr := err.(MultiError); isMultiErr { 43 return ExpandAll(common.FilterNotNil(multiErr.Unwrap())) 44 } else { 45 return []error{err} 46 } 47 } 48 49 func ExpandAll(errs []error) []error { 50 return common.FlatMap(errs, Expand) 51 } 52 53 func Append(err error, other error, block func(error) error) error { 54 if other == nil { 55 return err 56 } 57 return Errors(err, block(other)) 58 } 59 60 func IsMulti(err error, targetList ...error) bool { 61 for _, target := range targetList { 62 if errors.Is(err, target) { 63 return true 64 } 65 } 66 err = Unwrap(err) 67 multiErr, isMulti := err.(MultiError) 68 if !isMulti { 69 return false 70 } 71 return common.All(multiErr.Unwrap(), func(it error) bool { 72 return IsMulti(it, targetList...) 73 }) 74 }