-
Notifications
You must be signed in to change notification settings - Fork 0
/
errors.go
163 lines (143 loc) · 3.12 KB
/
errors.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
161
162
163
// Licensed under the GPLv3, see LICENCE file for details.
package bulkerrs
import (
"bytes"
"fmt"
"github.com/juju/errors"
)
// Errs holds an array of JujuErr (juju/errors).
//
// It may be embedded in also custom error types that have been converted to JujuErr.
type Errs struct {
// holds inner errors
errors []JujuErr
}
// If an error complies this interface, then it's a juju error :)
type JujuErr interface {
Cause() error
Error() string
Format(fmt.State, rune)
Location() (string, int)
Message() string
SetLocation(int)
StackTrace() []string
Underlying() error
}
// Juju Error function interfaces
type NewXFn func(error, string) error
// Aux Juju Error constructor, panics if argument error is nil
func getJujuErr(err error) JujuErr {
if err == nil {
panic("Error is nil")
}
jErr, ok := err.(JujuErr)
if !ok {
newerr := errors.Annotate(err, err.Error())
jErr = newerr.(JujuErr)
jErr.SetLocation(2)
}
return jErr
}
func NewErr() Errs {
return Errs{}
}
func NewErrOr(err error) Errs {
if err == nil {
return Errs{}
} else if myerr, ok := err.(*Errs); ok {
return *myerr
} else {
return Errs{
errors: []JujuErr{getJujuErr(err)},
}
}
}
func (e *Errs) NewErr(format string, args ...interface{}) {
err := errors.NewErr(format, args...)
err.SetLocation(1)
e.errors = append(e.errors, &err)
}
func (e *Errs) NewErrWithCause(other error, format string, args ...interface{}) {
err := errors.NewErrWithCause(other, format, args...)
err.SetLocation(1)
e.errors = append(e.errors, &err)
}
func (e *Errs) Append(errs ...error) bool {
result := false
for _, err := range errs {
if err == nil {
// pass
} else if myerr, ok := err.(*Errs); ok {
e.errors = append(e.errors, myerr.errors...)
} else {
e.errors = append(e.errors, getJujuErr(err))
}
result = true
}
return result
}
// Appends error if condition, returns condition
func (e *Errs) AppendIf(condition bool, msg string) bool {
if condition {
err := errors.New(msg).(JujuErr)
err.SetLocation(1)
e.Append(err)
}
return condition
}
func (e *Errs) AppendIfX(condition bool, newErr NewXFn, msg string, other error) bool {
if condition {
err := newErr(other, msg).(JujuErr)
err.SetLocation(1)
e.Append(err)
}
return condition
}
func Concat(errs ...error) Errs {
err := NewErr()
for _, erri := range errs {
err.Append(erri)
}
return err
}
func (e Errs) ToError() error {
if len(e.errors) == 0 {
return nil
}
return &e
}
func (e *Errs) Error() string {
var buffer bytes.Buffer
for i, err := range e.errors {
if i != 0 {
buffer.WriteString("\n")
}
buffer.WriteString(err.Error())
}
return buffer.String()
}
func (e *Errs) Errors() []string {
errs := make([]string, len(e.errors))
for i, err := range e.errors {
errs[i] = err.Error()
}
return errs
}
func (e *Errs) InnerErrors() []error {
errs := make([]error, len(e.errors))
for i, err := range e.errors {
errs[i] = err
}
return errs
}
func (e Errs) Format(s fmt.State, verb rune) {
fmt.Fprintf(s, "[")
max_idx := len(e.errors) - 1
for i, err := range e.errors {
err.Format(s, verb)
if i != max_idx {
fmt.Fprintf(s, ", ")
}
}
fmt.Fprintf(s, "]")
}