github.com/alloyzeus/go-azfl@v0.0.0-20231220071816-9740126a2d07/azerrs/context.go (about) 1 package errors 2 3 import "strings" 4 5 type ContextError interface { 6 CallError 7 ContextError() ContextError 8 } 9 10 type ContextErrorBuilder interface { 11 ContextError 12 13 // Desc returns a copy with descriptor is set to desc. 14 Desc(desc ErrorDescriptor) ContextErrorBuilder 15 16 // DescMsg sets the descriptor with the provided string. For the best 17 // experience, descMsg should be defined as a constant so that the error 18 // users could use it to identify an error. For non-constant descriptor 19 // use the Wrap method. 20 DescMsg(descMsg string) ContextErrorBuilder 21 22 // Wrap returns a copy with wrapped error is set to detailingError. 23 Wrap(detailingError error) ContextErrorBuilder 24 25 Fieldset(fields ...NamedError) ContextErrorBuilder 26 } 27 28 func IsContextError(err error) bool { 29 _, ok := err.(ContextError) 30 return ok 31 } 32 33 func Context() ContextErrorBuilder { 34 return &contextError{} 35 } 36 37 func ContextUnspecified() ContextErrorBuilder { 38 return Context().Wrap(ErrValueUnspecified) 39 } 40 41 func IsContextUnspecifiedError(err error) bool { 42 if !IsContextError(err) { 43 return false 44 } 45 if desc := UnwrapDescriptor(err); desc != nil { 46 return desc == ErrValueUnspecified 47 } 48 return false 49 } 50 51 type contextError struct { 52 descriptor ErrorDescriptor 53 wrapped error 54 fields []NamedError 55 } 56 57 var ( 58 _ error = &contextError{} 59 _ CallError = &contextError{} 60 _ ContextError = &contextError{} 61 _ ContextErrorBuilder = &contextError{} 62 _ Unwrappable = &contextError{} 63 ) 64 65 func (e *contextError) Error() string { 66 suffix := e.fieldErrorsAsString() 67 if suffix != "" { 68 suffix = ": " + suffix 69 } 70 var descStr string 71 if e.descriptor != nil { 72 descStr = e.descriptor.Error() 73 } 74 causeStr := errorString(e.wrapped) 75 if causeStr == "" { 76 causeStr = descStr 77 } else if descStr != "" { 78 causeStr = descStr + ": " + causeStr 79 } 80 81 if causeStr != "" { 82 return "context " + causeStr + suffix 83 } 84 return "context invalid" + suffix 85 } 86 87 func (e *contextError) CallError() CallError { return e } 88 func (e *contextError) ContextError() ContextError { return e } 89 func (e *contextError) Unwrap() error { return e.wrapped } 90 91 func (e contextError) fieldErrorsAsString() string { 92 if flen := len(e.fields); flen > 0 { 93 parts := make([]string, 0, flen) 94 for _, sub := range e.fields { 95 parts = append(parts, sub.Error()) 96 } 97 return strings.Join(parts, ", ") 98 } 99 return "" 100 } 101 102 func (e contextError) Descriptor() ErrorDescriptor { 103 if e.descriptor != nil { 104 return e.descriptor 105 } 106 if desc, ok := e.wrapped.(ErrorDescriptor); ok { 107 return desc 108 } 109 return nil 110 } 111 112 func (e contextError) Desc(desc ErrorDescriptor) ContextErrorBuilder { 113 e.descriptor = desc 114 return &e 115 } 116 117 func (e contextError) DescMsg(descMsg string) ContextErrorBuilder { 118 e.descriptor = constantErrorDescriptor(descMsg) 119 return &e 120 } 121 122 func (e contextError) Fieldset(fields ...NamedError) ContextErrorBuilder { 123 e.fields = fields // copy? 124 return &e 125 } 126 127 func (e contextError) Wrap(detailingError error) ContextErrorBuilder { 128 e.wrapped = detailingError 129 return &e 130 }