forked from pingcap/errcode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwrap.go
160 lines (135 loc) · 4.53 KB
/
wrap.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package errcode
import (
"github.com/gregwebs/errors"
"github.com/gregwebs/errors/errwrap"
"github.com/gregwebs/errors/slogerr"
)
// Wrap calls errors.Wrap on the inner error.
// This will wrap in place via errors.ErrorWrapper if available
// If a nil is given it is a noop
func Wrap(errCode ErrorCode, msg string) ErrorCode {
//nolint:govet
return wrapG(wrapWith, errCode, msg)
}
// Wrapf calls errors.Wrapf on the inner error.
// This will wrap in place via errors.ErrorWrapper if available
// If a nil is given it is a noop
func Wrapf(errCode ErrorCode, msg string, args ...interface{}) ErrorCode {
return wrapG(wrapWith, errCode, msg, args...)
}
// Wraps calls errors.Wraps on the inner error.
// This will wrap in place via errors.ErrorWrapper if available
// If a nil is given it is a noop
func Wraps(errCode ErrorCode, msg string, args ...interface{}) ErrorCode {
return wrapWith(errCode, slogerr.WrapsFn(msg, args...))
}
// WrapUser calls errors.Wrap on the inner error.
// This will wrap in place via errors.ErrorWrapper if available
// If a nil is given it is a noop
func WrapUser(errCode UserCode, msg string) UserCode {
//nolint:govet
return wrapG(wrapUserWith, errCode, msg)
}
// WrapUserf calls errors.Wrapf on the inner error.
// This will wrap in place via errors.ErrorWrapper if available
// If a nil is given it is a noop
func WrapfUser(errCode UserCode, msg string, args ...interface{}) UserCode {
return wrapG(wrapUserWith, errCode, msg, args...)
}
// WrapsUser calls errors.Wraps on the inner error.
// This uses the WrapError method of ErrorWrap
// If a nil is given it is a noop
func WrapsUser(errCode UserCode, msg string, args ...interface{}) UserCode {
return wrapUserWith(errCode, slogerr.WrapsFn(msg, args...))
}
// WrapOp calls errors.Wrap on the inner error.
// This will wrap in place via errors.ErrorWrapper if available
// If a nil is given it is a noop
func WrapOp(errCode OpCode, msg string) OpCode {
//nolint:govet
return wrapG(wrapOpWith, errCode, msg)
}
// WrapOpf calls errors.Wrapf on the inner error.
// This will wrap in place via errors.ErrorWrapper if available
// If a nil is given it is a noop
func WrapfOp(errCode OpCode, msg string, args ...interface{}) OpCode {
return wrapG(wrapOpWith, errCode, msg, args...)
}
// WrapsOp calls errors.Wraps on the inner error.
// This uses the WrapError method of ErrorWrap
// If a nil is given it is a noop
func WrapsOp(errCode OpCode, msg string, args ...interface{}) OpCode {
return wrapOpWith(errCode, slogerr.WrapsFn(msg, args...))
}
func wrapWith(errCode ErrorCode, wrap func(error) error) ErrorCode {
if errCode == nil {
return errCode
}
ok := errwrap.WrapInPlace(errCode, wrap)
if ok {
return errCode
}
return wrappedErrorCode{newWithError(errCode, wrap)}
}
func wrapUserWith(errCode UserCode, wrap func(error) error) UserCode {
if errCode == nil {
return errCode
}
ok := errwrap.WrapInPlace(errCode, wrap)
if ok {
return errCode
}
return wrappedUserCode{newWithError(errCode, wrap)}
}
func wrapOpWith(errCode OpCode, wrap func(error) error) OpCode {
if errCode == nil {
return errCode
}
ok := errwrap.WrapInPlace(errCode, wrap)
if ok {
return errCode
}
return wrappedOpCode{newWithError(errCode, wrap)}
}
// unwrapError allows the abstract retrieval of the underlying error.
// Formalize the Unwrap interface, but don't export it.
// The standard library errors package should export it.
// Types that wrap errors should implement this to allow viewing of the underlying error.
type unwrapError interface {
Unwrap() error
}
type withError[T any] struct {
With T
*errwrap.ErrorWrap
}
// do a nil check before calling this
func newWithError[Err error](errCode Err, wrapErr func(error) error) withError[Err] {
return withError[Err]{
With: errCode,
ErrorWrap: errwrap.NewErrorWrap(wrapErr(errCode)),
}
}
type wrappedErrorCode struct{ withError[ErrorCode] }
func (wec wrappedErrorCode) Code() Code {
return wec.With.Code()
}
type wrappedUserCode struct{ withError[UserCode] }
func (wec wrappedUserCode) Code() Code {
return wec.With.Code()
}
func (wec wrappedUserCode) GetUserMsg() string {
return wec.With.GetUserMsg()
}
type wrappedOpCode struct{ withError[OpCode] }
func (wec wrappedOpCode) Code() Code {
return wec.With.Code()
}
func (wec wrappedOpCode) GetOperation() string {
return wec.With.GetOperation()
}
func wrapG[Err ErrorCode](errWrap func(Err, func(error) error) Err, errCode Err, msg string, args ...interface{}) Err {
if len(args) == 0 {
return errWrap(errCode, errors.WrapFn(msg))
}
return errWrap(errCode, errors.WrapfFn(msg, args...))
}