-
Notifications
You must be signed in to change notification settings - Fork 26
/
werror.go
81 lines (71 loc) · 1.58 KB
/
werror.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
// Copyright 2023 PingCAP, Inc.
// SPDX-License-Identifier: Apache-2.0
package errors
import (
"errors"
"fmt"
)
var (
_ error = &WError{}
)
type WError struct {
uerr error
cerr error
}
func (e *WError) Format(st fmt.State, verb rune) {
switch verb {
case 'v':
if st.Flag('+') {
fmt.Fprintf(st, "%+v: %+v", e.cerr, e.uerr)
} else {
fmt.Fprintf(st, "%v: %v", e.cerr, e.uerr)
}
case 's':
if st.Flag('+') {
fmt.Fprintf(st, "%+s: %+s", e.cerr, e.uerr)
} else {
fmt.Fprintf(st, "%s: %s", e.cerr, e.uerr)
}
}
}
func (e *WError) Error() string {
return fmt.Sprintf("%s", e)
}
func (e *WError) Is(s error) bool {
r := errors.Is(e.cerr, s)
if r {
return r
}
return errors.Is(e.uerr, s)
}
func (e *WError) Unwrap() error {
return e.uerr
}
// Wrap is used to wrapping unknown errors. A typical example is that:
// 1. have a function `ReadMyConfig()`
// 2. it got errors returned from external libraries
// 3. you want to wrap these errors, expect `Unwrap(err) == ErrExternalErrors && Is(err, ErrReadMyConfig) && Is(err, ErrExternalErrors)`.
// 4. then you are finding `err := Wrap(ErrReadMyConfig, ErrExternalErrors)`
// Note that wrap nil error will get nil error.
func Wrap(cerr error, uerr error) error {
if cerr == nil {
return uerr
}
if uerr == nil {
return nil
}
return &WError{
uerr: uerr,
cerr: cerr,
}
}
// Wrapf is like Wrap, with the underlying error being the result of `fmt.Errorf()`
func Wrapf(cerr error, msg string, args ...interface{}) error {
if cerr == nil {
return nil
}
return &WError{
uerr: fmt.Errorf(msg, args...),
cerr: cerr,
}
}