• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ghettovoice / abnf / 18794565666

24 Oct 2025 11:24PM UTC coverage: 71.139% (+2.6%) from 68.56%
18794565666

push

github

ghettovoice
Memory allocation optimizations

- disable by default error wrapping and provide methods to enable it;
- new method to check node cache stats;
- minor fixes and refactoring.

88 of 113 new or added lines in 3 files covered. (77.88%)

2 existing lines in 2 files now uncovered.

1612 of 2266 relevant lines covered (71.14%)

54.67 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.26
/errors.go
1
package abnf
2

3
import (
4
        "bytes"
5
        "errors"
6
        "fmt"
7
        "strings"
8
        "sync"
9
        "sync/atomic"
10
)
11

12
const (
13
        // ErrNotMatched returned by operators if input doesn't match
14
        ErrNotMatched sentinelError = "not matched"
15
)
16

17
var detailErrs atomic.Bool
18

19
// EnableDetailedErrors enables detailed operator errors.
20
func EnableDetailedErrors() { detailErrs.Store(true) }
1✔
21

22
// DisableDetailedErrors disables detailed operator errors.
23
func DisableDetailedErrors() { detailErrs.Store(false) }
1✔
24

25
type sentinelError string
26

27
func (e sentinelError) Error() string { return string(e) }
2✔
28

29
type operError struct {
30
        op  string
31
        pos uint
32
        err error
33
}
34

35
func (e operError) Unwrap() error { return e.err }
2✔
36

37
func (e operError) Error() string {
1✔
38
        sb := bytes.NewBuffer(make([]byte, 0, 128))
1✔
39
        e.writeError(sb, 0)
1✔
40
        return sb.String()
1✔
41
}
1✔
42

43
func (e operError) writeError(sb *bytes.Buffer, depth int) {
4✔
44
        fmt.Fprintf(sb, "operator %q failed at position %d:", e.op, e.pos)
4✔
45

4✔
46
        var merr *multiError
4✔
47
        if errors.As(e.err, &merr) {
6✔
48
                merr.writeError(sb, depth)
2✔
49
        } else {
4✔
50
                sb.WriteString(" ")
2✔
51
                sb.WriteString(e.err.Error())
2✔
52
        }
2✔
53
}
54

55
type multiError []error
56

57
func (e *multiError) Unwrap() []error {
11✔
58
        if e == nil {
11✔
NEW
59
                return nil
×
NEW
60
        }
×
61
        return *e
11✔
62
}
63

NEW
64
func (e *multiError) Error() string {
×
NEW
65
        if e == nil {
×
NEW
66
                return "<nil>"
×
NEW
67
        }
×
68

NEW
69
        sb := bytes.NewBuffer(make([]byte, 0, 128))
×
NEW
70
        e.writeError(sb, 0)
×
71
        return sb.String()
×
72
}
73

74
func (e *multiError) writeError(sb *bytes.Buffer, depth int) {
2✔
75
        sb.WriteString("\n")
2✔
76

2✔
77
        for i, err := range *e {
5✔
78
                if i > 0 {
4✔
79
                        sb.WriteString("\n")
1✔
80
                }
1✔
81

82
                var (
3✔
83
                        me *multiError
3✔
84
                        oe operError
3✔
85
                )
3✔
86
                if errors.As(err, &oe) {
6✔
87
                        sb.WriteString(strings.Repeat("  ", depth+1))
3✔
88
                        sb.WriteString("- ")
3✔
89
                        oe.writeError(sb, depth+1)
3✔
90
                } else if errors.As(err, &me) {
3✔
NEW
91
                        me.writeError(sb, depth+1)
×
92
                } else {
×
NEW
93
                        sb.WriteString(strings.Repeat("  ", depth+1))
×
NEW
94
                        sb.WriteString("- ")
×
NEW
95
                        sb.WriteString(err.Error())
×
UNCOV
96
                }
×
97
        }
98
}
99

100
const multiErrCap = 3
101

102
var multiErrPool = &sync.Pool{
103
        New: func() any {
11✔
104
                me := make(multiError, 0, multiErrCap)
11✔
105
                return &me
11✔
106
        },
11✔
107
}
108

109
func newMultiErr(c uint) *multiError {
29✔
110
        var err *multiError
29✔
111
        if c <= multiErrCap {
58✔
112
                err = multiErrPool.Get().(*multiError)
29✔
113
        } else {
29✔
114
                me := make(multiError, 0, c)
×
115
                err = &me
×
116
        }
×
117
        return err
29✔
118
}
119

120
func (e *multiError) clear() {
111✔
121
        if e == nil {
170✔
122
                return
59✔
123
        }
59✔
124

125
        clear(*e)
52✔
126
        *e = (*e)[:0]
52✔
127
}
128

129
func (e *multiError) free() {
41✔
130
        if e == nil || cap(*e) > 10*multiErrCap {
56✔
131
                return
15✔
132
        }
15✔
133

134
        e.clear()
26✔
135
        multiErrPool.Put(e)
26✔
136
}
137

138
func wrapOperError(op string, pos uint, err error) error {
67✔
139
        if err == nil {
67✔
NEW
140
                return nil
×
NEW
141
        }
×
142

143
        if !detailErrs.Load() {
128✔
144
                if errors.Is(err, ErrNotMatched) {
122✔
145
                        if me, ok := err.(*multiError); ok {
69✔
146
                                me.free()
8✔
147
                        }
8✔
148
                        if oe, ok := err.(operError); ok {
61✔
NEW
149
                                if me, ok := oe.err.(*multiError); ok {
×
NEW
150
                                        me.free()
×
NEW
151
                                }
×
152
                        }
153
                        return ErrNotMatched
61✔
154
                }
NEW
155
                return err
×
156
        }
157

158
        var oerr operError
6✔
159
        if errors.As(err, &oerr) && oerr.op == op && oerr.pos == pos {
6✔
NEW
160
                return err
×
NEW
161
        }
×
162

163
        return operError{op: op, pos: pos, err: err}
6✔
164
}
165

166
func wrapNotMatched(op string, pos uint) error {
53✔
167
        return wrapOperError(op, pos, ErrNotMatched)
53✔
168
}
53✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc