github.com/sagernet/sing@v0.2.6/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.UniqBy(errors, error.Error) 27 switch len(errors) { 28 case 0: 29 return nil 30 case 1: 31 return errors[0] 32 } 33 return &multiError{ 34 errors: errors, 35 } 36 } 37 38 func Expand(err error) []error { 39 if multiErr, isMultiErr := err.(MultiError); isMultiErr { 40 return ExpandAll(multiErr.Unwrap()) 41 } 42 return []error{err} 43 } 44 45 func ExpandAll(errs []error) []error { 46 return common.FlatMap(errs, Expand) 47 } 48 49 func Append(err error, other error, block func(error) error) error { 50 if other == nil { 51 return err 52 } 53 return Errors(err, block(other)) 54 } 55 56 func IsMulti(err error, targetList ...error) bool { 57 for _, target := range targetList { 58 if errors.Is(err, target) { 59 return true 60 } 61 } 62 err = Unwrap(err) 63 multiErr, isMulti := err.(MultiError) 64 if !isMulti { 65 return false 66 } 67 return common.All(multiErr.Unwrap(), func(it error) bool { 68 return IsMulti(it, targetList...) 69 }) 70 }