/
error.go
224 lines (183 loc) · 5.94 KB
/
error.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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
package netutil
import (
"fmt"
"github.com/AdguardTeam/golibs/errors"
)
// Errors
//
// TODO(a.garipov): Implement the errors.Iser interface and use errors.Is in
// tests to test the whole content of the errors.
const (
// ErrNotAReversedIP is the underlying error returned from validation
// functions when a domain name is not a full reversed IP address.
ErrNotAReversedIP errors.Error = "not a full reversed ip address"
// ErrNotAReversedSubnet is the underlying error returned from validation
// functions when a domain name is not a valid reversed IP network.
ErrNotAReversedSubnet errors.Error = "not a reversed ip network"
)
// AddrKind is a convenient alias for string describing the kind of address and
// used for error reporting.
type AddrKind = string
// Kinds of addresses for [AddrError].
const (
AddrKindARPA AddrKind = "arpa domain name"
AddrKindCIDR AddrKind = "cidr address"
AddrKindHostPort AddrKind = "hostport address"
AddrKindIP AddrKind = "ip address"
AddrKindIPPort AddrKind = "ipport address"
AddrKindIPv4 AddrKind = "ipv4 address"
AddrKindMAC AddrKind = "mac address"
AddrKindName AddrKind = "hostname"
AddrKindDomainName AddrKind = "domain name"
AddrKindSRVName AddrKind = "service domain name"
)
// AddrError is the underlying type of errors returned from validation
// functions when a domain name is invalid.
type AddrError struct {
// Err is the underlying error, if any.
Err error
// Kind is the kind of address or address part.
Kind AddrKind
// Addr is the text of the invalid address.
Addr string
}
// type check
var _ error = (*AddrError)(nil)
// Error implements the error interface for *AddrError.
func (err *AddrError) Error() (msg string) {
if err.Err != nil {
return fmt.Sprintf("bad %s %q: %s", err.Kind, err.Addr, err.Err)
}
return fmt.Sprintf("bad %s %q", err.Kind, err.Addr)
}
// type check
var _ errors.Wrapper = (*AddrError)(nil)
// Unwrap implements the [errors.Wrapper] interface for *AddrError. It returns
// err.Err.
func (err *AddrError) Unwrap() (unwrapped error) {
return err.Err
}
// makeAddrError is a deferrable helper for functions that return [*AddrError].
// errPtr must be non-nil. Usage example:
//
// defer makeAddrError(&err, addr, AddrKindARPA)
func makeAddrError(errPtr *error, addr string, k AddrKind) {
err := *errPtr
if err == nil {
return
}
*errPtr = &AddrError{
Err: err,
Kind: k,
Addr: addr,
}
}
// LabelKind is a convenient alias for string describing the kind of label of a
// name and used for error reporting.
type LabelKind = string
// Kinds of labels for [LabelError].
const (
LabelKindDomain LabelKind = "domain name label"
LabelKindHost LabelKind = "hostname label"
LabelKindSRV LabelKind = "service name label"
LabelKindTLD LabelKind = "top-level domain name label"
)
// LabelError is the underlying type of errors returned from validation
// functions when a label of a name is invalid.
type LabelError struct {
// Err is the underlying error, if any.
Err error
// Kind is the kind of label of the name.
Kind LabelKind
// Label is the text of the invalid label.
Label string
}
// type check
var _ error = (*AddrError)(nil)
// Error implements the error interface for *AddrError.
func (err *LabelError) Error() (msg string) {
if err.Err != nil {
return fmt.Sprintf("bad %s %q: %s", err.Kind, err.Label, err.Err)
}
return fmt.Sprintf("bad %s %q", err.Kind, err.Label)
}
// type check
var _ errors.Wrapper = (*AddrError)(nil)
// Unwrap implements the [errors.Wrapper] interface for *AddrError. It returns
// err.Err.
func (err *LabelError) Unwrap() (unwrapped error) {
return err.Err
}
// makeLabelError is a deferrable helper for functions that return
// [*LabelError]. errPtr must be non-nil. Usage example:
//
// defer makeLabelError(&err, label, LabelKindDomain)
func makeLabelError(errPtr *error, label string, k LabelKind) {
err := *errPtr
if err == nil {
return
}
*errPtr = &LabelError{
Err: err,
Kind: k,
Label: label,
}
}
// LengthError is the underlying type of errors returned from validation
// functions when an address or a part of an address has a bad length. Kind is
// either [AddrKind] or [LabelKind].
type LengthError struct {
// Kind is the kind of address or address part.
Kind string
// Allowed are the allowed lengths for this kind of address. If allowed
// is empty, Max should be non-zero.
Allowed []int
// Max is the maximum length for this part or address kind. If Max is
// zero, Allowed should be non-empty.
Max int
// Length is the length of the provided address.
Length int
}
// Error implements the error interface for *LengthError.
func (err *LengthError) Error() (msg string) {
if err.Max > 0 {
return fmt.Sprintf("%s is too long: got %d, max %d", err.Kind, err.Length, err.Max)
}
if err.Length == 0 {
return fmt.Sprintf("%s is empty", err.Kind)
}
format := "bad %s length %d, allowed: %v"
if len(err.Allowed) == 1 {
return fmt.Sprintf(format, err.Kind, err.Length, err.Allowed[0])
}
return fmt.Sprintf(format, err.Kind, err.Length, err.Allowed)
}
// RuneError is the underlying type of errors returned from validation functions
// when a rune in the address is invalid. Kind is either [AddrKind] or
// [LabelKind].
type RuneError struct {
// Kind is the kind of address or address part.
Kind string
// Rune is the invalid rune.
Rune rune
}
// Error implements the error interface for *RuneError.
func (err *RuneError) Error() (msg string) {
return fmt.Sprintf("bad %s rune %q", err.Kind, err.Rune)
}
// replaceKind replaces the Kind field of err with newKind. err must be of type
// [*LabelError], [*AddrError], [*LengthError], or [*RuneError].
func replaceKind(err error, newKind string) {
switch err := err.(type) {
case *LabelError:
err.Kind = newKind
case *AddrError:
err.Kind = newKind
case *LengthError:
err.Kind = newKind
case *RuneError:
err.Kind = newKind
default:
panic(fmt.Errorf("netutil: unexpected error type %T", err))
}
}