2020-10-19 21:40:00 +00:00
|
|
|
package merror
|
|
|
|
|
2021-10-16 21:11:32 +00:00
|
|
|
import "sync"
|
|
|
|
|
2020-10-19 21:40:00 +00:00
|
|
|
// MError represents zero or more errors that can be
|
|
|
|
// accumulated via the `Append` method.
|
|
|
|
type MError struct {
|
2021-10-16 21:11:32 +00:00
|
|
|
cap int
|
|
|
|
|
|
|
|
mux sync.RWMutex
|
2020-10-19 21:40:00 +00:00
|
|
|
errors []error
|
|
|
|
overflow int
|
|
|
|
formatter FormatterFunc
|
|
|
|
}
|
|
|
|
|
|
|
|
// New returns a new instance of `MError` with no limit on the
|
|
|
|
// number of errors that can be appended.
|
|
|
|
func New() *MError {
|
|
|
|
me := &MError{}
|
|
|
|
me.errors = make([]error, 0, 10)
|
|
|
|
return me
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewWithCap returns a new instance of `MError` with a maximum
|
|
|
|
// capacity of `cap` errors. If exceeded only the overflow counter
|
|
|
|
// will be incremented.
|
|
|
|
//
|
|
|
|
// A `cap` of zero of less means no cap and max size of a slice
|
|
|
|
// on the current platform is the upper bound.
|
|
|
|
func NewWithCap(cap int) *MError {
|
|
|
|
me := New()
|
|
|
|
me.cap = cap
|
|
|
|
return me
|
|
|
|
}
|
|
|
|
|
|
|
|
// Append adds an error to the aggregated error list.
|
|
|
|
func (me *MError) Append(err error) {
|
|
|
|
if err == nil {
|
|
|
|
return
|
|
|
|
}
|
2021-10-16 21:11:32 +00:00
|
|
|
|
|
|
|
me.mux.Lock()
|
|
|
|
defer me.mux.Unlock()
|
|
|
|
|
2020-10-19 21:40:00 +00:00
|
|
|
if me.cap > 0 && len(me.errors) >= me.cap {
|
|
|
|
me.overflow++
|
|
|
|
} else {
|
|
|
|
me.errors = append(me.errors, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-16 21:11:32 +00:00
|
|
|
// Errors returns a slice of the `error` instances that have been
|
2020-10-19 21:40:00 +00:00
|
|
|
// appended to this `MError`.
|
|
|
|
func (me *MError) Errors() []error {
|
2021-10-16 21:11:32 +00:00
|
|
|
me.mux.RLock()
|
|
|
|
defer me.mux.RUnlock()
|
|
|
|
|
|
|
|
errs := make([]error, len(me.errors))
|
|
|
|
copy(errs, me.errors)
|
|
|
|
|
|
|
|
return errs
|
2020-10-19 21:40:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Len returns the number of errors that have been appended.
|
|
|
|
func (me *MError) Len() int {
|
2021-10-16 21:11:32 +00:00
|
|
|
me.mux.RLock()
|
|
|
|
defer me.mux.RUnlock()
|
|
|
|
|
2020-10-19 21:40:00 +00:00
|
|
|
return len(me.errors)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Overflow returns the number of errors that have been truncated
|
|
|
|
// because maximum capacity was exceeded.
|
|
|
|
func (me *MError) Overflow() int {
|
2021-10-16 21:11:32 +00:00
|
|
|
me.mux.RLock()
|
|
|
|
defer me.mux.RUnlock()
|
|
|
|
|
2020-10-19 21:40:00 +00:00
|
|
|
return me.overflow
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetFormatter sets the `FormatterFunc` to be used when `Error` is
|
|
|
|
// called. The previous `FormatterFunc` is returned.
|
|
|
|
func (me *MError) SetFormatter(f FormatterFunc) (old FormatterFunc) {
|
2021-10-16 21:11:32 +00:00
|
|
|
me.mux.Lock()
|
|
|
|
defer me.mux.Unlock()
|
|
|
|
|
2020-10-19 21:40:00 +00:00
|
|
|
old = me.formatter
|
|
|
|
me.formatter = f
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// ErrorOrNil returns nil if this `MError` contains no errors,
|
|
|
|
// otherwise this `MError` is returned.
|
|
|
|
func (me *MError) ErrorOrNil() error {
|
2021-10-16 21:11:32 +00:00
|
|
|
if me == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
me.mux.RLock()
|
|
|
|
defer me.mux.RUnlock()
|
|
|
|
|
|
|
|
if len(me.errors) == 0 {
|
2020-10-19 21:40:00 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return me
|
|
|
|
}
|
|
|
|
|
|
|
|
// Error returns a string representation of this MError.
|
|
|
|
// The output format depends on the `Formatter` set for this
|
|
|
|
// merror instance, or the global formatter if none set.
|
|
|
|
func (me *MError) Error() string {
|
2021-10-16 21:11:32 +00:00
|
|
|
me.mux.RLock()
|
|
|
|
defer me.mux.RUnlock()
|
|
|
|
|
2020-10-19 21:40:00 +00:00
|
|
|
f := me.formatter
|
|
|
|
if f == nil {
|
|
|
|
f = GlobalFormatter
|
|
|
|
}
|
|
|
|
return f(me)
|
|
|
|
}
|