-
Notifications
You must be signed in to change notification settings - Fork 0
/
error_list.go
103 lines (90 loc) · 1.98 KB
/
error_list.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
package errkit
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"strconv"
)
type ErrorList []error
var _ error = (ErrorList)(nil)
var _ json.Marshaler = (ErrorList)(nil)
func (e ErrorList) String() string {
sep := ""
var buf bytes.Buffer
buf.WriteRune('[')
for _, err := range e {
buf.WriteString(sep)
sep = ","
buf.WriteString(strconv.Quote(err.Error()))
}
buf.WriteRune(']')
return buf.String()
}
func (e ErrorList) Error() string {
return e.String()
}
// As allows error.As to work against any error in the list.
func (e ErrorList) As(target any) bool {
for _, err := range e {
if errors.As(err, target) {
return true
}
}
return false
}
// Is allows error.Is to work against any error in the list.
func (e ErrorList) Is(target error) bool {
for _, err := range e {
if errors.Is(err, target) {
return true
}
}
return false
}
func (e ErrorList) MarshalJSON() ([]byte, error) {
var je struct {
Message string `json:"message"`
Errors []json.RawMessage `json:"errors"`
}
switch len(e) {
case 0:
// no errors
return []byte("null"), nil
case 1:
// this is unlikely to happen as kerrors.Append won't allow having just a single error on the list
je.Message = "1 error has occurred"
default:
je.Message = fmt.Sprintf("%d errors have occurred", len(e))
}
je.Errors = make([]json.RawMessage, 0, len(e))
for i := range e {
raw, err := json.Marshal(jsonMarshable(e[i]))
if err != nil {
return nil, err
}
je.Errors = append(je.Errors, raw)
}
return json.Marshal(je)
}
// Append creates a new combined error from err1, err2. If either error is nil,
// then the other error is returned.
func Append(err1, err2 error) error {
if err1 == nil {
return ErrorList{err2}
}
if err2 == nil {
return ErrorList{err1}
}
el1, ok1 := err1.(ErrorList)
el2, ok2 := err2.(ErrorList)
switch {
case ok1 && ok2:
return append(el1, el2...)
case ok1:
return append(el1, err2)
case ok2:
return append(el2, err1)
}
return ErrorList{err1, err2}
}