Repository navigation
Expand file tree
/
Copy patherrors.go
More file actions
107 lines (95 loc) · 2.88 KB
/
Copy patherrors.go
File metadata and controls
107 lines (95 loc) · 2.88 KB
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
package errors
import "maps"
// Error carries immutable meaning and a private diagnostic frame.
// Use public accessors for responses; Error() is diagnostic text.
type Error struct {
kind Kind
message string
typ string
fields map[string]string
details map[string]string
cause error
condition *Error
}
// New constructs a real failure, including when its message is empty.
func New(kind Kind, message string) *Error { return &Error{kind: kind, message: message} }
// Wrap deliberately classifies a cause. Nil remains a nil error interface.
func Wrap(err error, kind Kind, message string) error {
if err == nil {
return nil
}
return New(kind, message).WithCause(err)
}
func (e *Error) Error() string {
if e == nil {
return "<nil>"
}
message := e.message
if message == "" {
message = e.kind.String()
}
if e.cause != nil {
return message + ": " + e.cause.Error()
}
return message
}
// Unwrap exposes the diagnostic cause to standard errors.Is and errors.As.
func (e *Error) Unwrap() error {
if e == nil {
return nil
}
return e.cause
}
func (e *Error) identity() *Error {
if e.condition != nil {
return e.condition
}
return e
}
// Is preserves condition identity across derivations; equal text is not identity.
func (e *Error) Is(target error) bool {
other, ok := target.(*Error)
return ok && e != nil && other != nil && e.identity() == other.identity()
}
func (e *Error) clone() *Error {
copy := *e
copy.condition = e.identity()
copy.fields = maps.Clone(e.fields)
copy.details = maps.Clone(e.details)
return ©
}
// WithType derives a public condition identifier.
func (e *Error) WithType(value string) *Error { copy := e.clone(); copy.typ = value; return copy }
// WithField derives a public problem. New values replace the same key.
func (e *Error) WithField(key, value string) *Error {
return e.WithFields(map[string]string{key: value})
}
// WithFields copies and merges public problems without aliasing the input.
func (e *Error) WithFields(values map[string]string) *Error {
copy := e.clone()
if len(values) != 0 {
if copy.fields == nil {
copy.fields = make(map[string]string, len(values))
}
maps.Copy(copy.fields, values)
}
return copy
}
// WithDetail derives a private diagnostic value.
func (e *Error) WithDetail(key, value string) *Error {
return e.WithDetails(map[string]string{key: value})
}
// WithDetails copies and merges private metadata; new values win.
func (e *Error) WithDetails(values map[string]string) *Error {
copy := e.clone()
if len(values) != 0 {
if copy.details == nil {
copy.details = make(map[string]string, len(values))
}
maps.Copy(copy.details, values)
}
return copy
}
// WithCause constructs an occurrence with a replacement source. A nil cause still
// produces a real failure; use Wrap for nil propagation.
func (e *Error) WithCause(cause error) *Error { copy := e.clone(); copy.cause = cause; return copy }