-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmetadata-error.go
80 lines (65 loc) · 1.28 KB
/
metadata-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
package errors
// WithMetadata annotates an error with metadata.
func WithMetadata(err error, meta any) error {
if meta == nil {
return err
}
return &metadataError{err, meta}
}
// Metadata returns the metadata associated with an error.
func Metadata(err error) any {
if err == nil {
return nil
}
me, ok := err.(iMetadataError)
if !ok {
return nil
}
return me.Metadata()
}
// TypedMetadata returns the metadata associated with an error.
// If the metadata is not of the specified type, ok is false.
func TypedMetadata[T any](err error) (ret T, ok bool) {
meta := Metadata(err)
if meta == nil {
return
}
ret, ok = meta.(T)
return
}
// TypedDeepMetadata returns the metadata of the specified type
// associated with an error or any of its wrappers.
func TypedDeepMetadata[T any](err error) (ret T, ok bool) {
for {
if err == nil {
return
}
ret, ok = TypedMetadata[T](err)
if ok {
return
}
err = Unwrap(err)
}
}
type iMetadataError interface {
error
Metadata() any
Unwrap() error
}
type metadataError struct {
error
meta any
}
var _ iMetadataError = (*metadataError)(nil)
func (m *metadataError) Metadata() any {
if m == nil {
return nil
}
return m.meta
}
func (m *metadataError) Unwrap() error {
if m == nil {
return nil
}
return m.error
}