-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patherrors.go
More file actions
154 lines (120 loc) · 2.93 KB
/
Copy patherrors.go
File metadata and controls
154 lines (120 loc) · 2.93 KB
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
package errors
import "fmt"
// Error is custom error.
type Error struct {
reason string
err error
x interface{}
}
// WithReason returns new Error with set error reason.
func WithReason(code string) *Error {
return &Error{reason: code, err: nil, x: nil}
}
// WithErr returns new Error with set error.
func WithErr(err error) *Error {
if err == nil {
return nil
}
return &Error{reason: "", err: err, x: nil}
}
// WithX returns new Error with set error data.
// Be aware that high-level WithX couldn't be recognised by Is and errors.Is.
// Do not use this constructor without especial necessity.
func WithX(x interface{}) *Error {
return &Error{reason: "", err: nil, x: x}
}
// WithReason sets error reason and returns self.
func (e *Error) WithReason(reason string) *Error {
if e == nil {
return WithReason(reason)
}
if e.reason != "" {
return &Error{reason: reason, err: e, x: nil}
}
return &Error{reason: reason, err: e.err, x: e.x}
}
// WithErr returns new Error with set sub-error.
// If current Error doesn't contain sub-error WithErr clones reason and data into new Error.
func (e *Error) WithErr(err error) *Error {
if e == nil {
return WithErr(err)
}
if e.err != nil {
var t *Error
if As(e.err, &t) {
err = t.WithErr(err)
} else {
err = &Error{reason: e.err.Error(), err: err, x: nil}
}
}
return &Error{reason: e.reason, err: err, x: e.x}
}
// WithX returns new Error with set data.
// If current Error already contains data WithX wrap current Error into sub-error.
// Otherwise WithX clones reason and sub-error into new Error.
func (e *Error) WithX(x interface{}) *Error {
if e == nil {
return WithX(x)
}
if e.x != nil {
return &Error{reason: "", err: e, x: x}
}
return &Error{reason: e.reason, err: e.err, x: x}
}
// IfErr sets error and returns self if specified err is not nil. Otherwise it returns nil.
// To be sure there is no case "nil is not always nil" IfErr returns built-in error interface.
func (e *Error) IfErr(err error) error {
if err == nil {
return nil
}
return e.WithErr(err)
}
// Error implements builtin/error interface.
func (e *Error) Error() string {
if e == nil {
return "nil"
}
s := ""
if e.reason != "" {
s += e.reason
}
if e.err != nil {
if len(s) > 0 {
s += " because: "
}
s += e.err.Error()
}
if e.x != nil {
if len(s) > 0 {
s += " with data: "
}
s += fmt.Sprintf("%T{%+v}", e.x, e.x)
}
return s
}
// Unwrap implements errors/Unwrap interface.
func (e *Error) Unwrap() error {
if e == nil {
return nil
}
return e.err
}
//nolint:gocognit
// Is implements errors/Is interface.
func (e *Error) Is(target error) bool {
if e == nil {
return target == nil
}
if e.Error() == target.Error() || e.reason == target.Error() {
return true
}
var t *Error
if !As(target, &t) {
if e.err == nil {
return target == nil
}
return Is(e.err, target)
}
return e.reason == t.reason && e.reason != "" ||
Is(e.err, t) || Is(e, t.err)
}