summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/wiggin77/merror/merror.go
blob: def753541533e347a77eb3f6f34eaeccb87488ee (plain) (blame)
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
package merror

import "sync"

// MError represents zero or more errors that can be
// accumulated via the `Append` method.
type MError struct {
	cap int

	mux       sync.RWMutex
	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
	}

	me.mux.Lock()
	defer me.mux.Unlock()

	if me.cap > 0 && len(me.errors) >= me.cap {
		me.overflow++
	} else {
		me.errors = append(me.errors, err)
	}
}

// Errors returns a slice of the `error` instances that have been
// appended to this `MError`.
func (me *MError) Errors() []error {
	me.mux.RLock()
	defer me.mux.RUnlock()

	errs := make([]error, len(me.errors))
	copy(errs, me.errors)

	return errs
}

// Len returns the number of errors that have been appended.
func (me *MError) Len() int {
	me.mux.RLock()
	defer me.mux.RUnlock()

	return len(me.errors)
}

// Overflow returns the number of errors that have been truncated
// because maximum capacity was exceeded.
func (me *MError) Overflow() int {
	me.mux.RLock()
	defer me.mux.RUnlock()

	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) {
	me.mux.Lock()
	defer me.mux.Unlock()

	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 {
	if me == nil {
		return nil
	}

	me.mux.RLock()
	defer me.mux.RUnlock()

	if len(me.errors) == 0 {
		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 {
	me.mux.RLock()
	defer me.mux.RUnlock()

	f := me.formatter
	if f == nil {
		f = GlobalFormatter
	}
	return f(me)
}