github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/depends/kit/validator/errors/errors_set.go (about) 1 package errors 2 3 import ( 4 "bytes" 5 "fmt" 6 7 "github.com/machinefi/w3bstream/pkg/depends/kit/statusx" 8 ) 9 10 func NewErrorSetWithRoot(root string) *ErrorSet { return &ErrorSet{root: root} } 11 12 func NewErrorSet() *ErrorSet { return &ErrorSet{root: ""} } 13 14 type ErrorSet struct { 15 root string 16 errors []*FieldError 17 } 18 19 func (set *ErrorSet) AddErr(err error, keyPathNodes ...interface{}) { 20 if err == nil { 21 return 22 } 23 set.errors = append(set.errors, &FieldError{KeyPath(keyPathNodes), err}) 24 } 25 26 func (set *ErrorSet) Each(cb func(*FieldError)) { 27 for _, fe := range set.errors { 28 cb(fe) 29 } 30 } 31 32 func (set *ErrorSet) Flatten() *ErrorSet { 33 ret := NewErrorSetWithRoot(set.root) 34 35 var walk func(*ErrorSet, ...interface{}) 36 37 walk = func(es *ErrorSet, patterns ...interface{}) { 38 es.Each(func(fe *FieldError) { 39 if sub, ok := fe.Error.(*ErrorSet); ok { 40 walk(sub, append(patterns, fe.Field...)...) 41 } else { 42 ret.AddErr(fe.Error, append(patterns, fe.Field...)...) 43 } 44 }) 45 } 46 47 walk(set) 48 49 return ret 50 } 51 func (set *ErrorSet) Len() int { return len(set.Flatten().errors) } 52 53 func (set *ErrorSet) Err() error { 54 if len(set.errors) == 0 { 55 return nil 56 } 57 return set 58 } 59 60 func (set *ErrorSet) Error() string { 61 errs := set.Flatten() 62 63 buf := bytes.Buffer{} 64 errs.Each( 65 func(f *FieldError) { 66 buf.WriteString(fmt.Sprintf("%s %s", f.Field, f.Error)) 67 buf.WriteRune('\n') 68 }, 69 ) 70 71 return buf.String() 72 } 73 74 type Location string 75 76 func (set *ErrorSet) ToErrorFields() statusx.ErrorFields { 77 errorFields := make([]*statusx.ErrorField, 0) 78 79 set.Flatten().Each(func(fieldErr *FieldError) { 80 if len(fieldErr.Field) > 0 { 81 if l, ok := fieldErr.Field[0].(Location); ok { 82 errorFields = append(errorFields, &statusx.ErrorField{ 83 In: string(l), 84 Field: fieldErr.Field[1:].String(), 85 Msg: fieldErr.Error.Error(), 86 }) 87 } 88 } 89 }) 90 91 return errorFields 92 } 93 94 type FieldError struct { 95 Field KeyPath 96 Error error `json:"msg"` 97 } 98 99 type KeyPath []interface{} 100 101 func (keyPath KeyPath) String() string { 102 buf := &bytes.Buffer{} 103 for i := 0; i < len(keyPath); i++ { 104 switch keyOrIndex := keyPath[i].(type) { 105 case string: 106 if buf.Len() > 0 { 107 buf.WriteRune('.') 108 } 109 buf.WriteString(keyOrIndex) 110 case int: 111 buf.WriteString(fmt.Sprintf("[%d]", keyOrIndex)) 112 } 113 } 114 return buf.String() 115 }