-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoperation.go
More file actions
120 lines (100 loc) · 2.57 KB
/
Copy pathoperation.go
File metadata and controls
120 lines (100 loc) · 2.57 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
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
* Copyright (c) 2024-2026 Mikhail Knyazhev <markus621@yandex.com>. All rights reserved.
* Use of this source code is governed by a BSD 3-Clause license that can be found in the LICENSE file.
*/
package errors
import (
e "errors"
"fmt"
"strings"
)
// Wrapf returns nil when cause is nil. Otherwise it prefixes cause with a
// formatted message and preserves cause for errors.Is and errors.As.
func Wrapf(cause error, message string, args ...any) error {
if cause == nil {
return nil
}
err := &errorEntity{
cause: cause,
message: message,
}
if len(args) > 0 {
err.message = fmt.Sprintf(message, args...)
}
return err
}
// Wrap combines non-nil errors into one error. Its message joins the input
// messages with ": ", and errors.Is and errors.As can inspect every input.
// Wrap returns nil when all inputs are nil.
func Wrap(messages ...error) error {
causes := make([]error, 0, len(messages))
for _, msg := range messages {
if msg == nil {
continue
}
causes = append(causes, msg)
}
switch len(causes) {
case 0:
return nil
case 1:
return &errorEntity{cause: causes[0]}
default:
return &joinedError{causes: causes}
}
}
// Unwrap returns the single wrapped error when err implements Unwrapper.
// It returns nil for nil errors and errors with multiple causes.
func Unwrap(err error) error {
if err == nil {
return nil
}
if v, ok := err.(Unwrapper); ok {
return v.Unwrap()
}
return nil
}
// Cause follows legacy Cause() methods and returns the first error that does
// not implement Causer. For errors wrapped with %w, use Is or As to inspect
// the chain.
func Cause(err error) error {
if err == nil {
return nil
}
for {
if c, ok := err.(Causer); ok && c != nil {
err = c.Cause()
continue
}
return err
}
}
// Is reports whether err or any error in its chain matches target.
func Is(err, target error) bool {
return e.Is(err, target)
}
// As finds the first error in err's chain assignable to target and stores it
// there, following the standard errors.As contract.
func As(err error, target any) bool {
return e.As(err, target)
}
type joinedError struct {
causes []error
}
func (v *joinedError) Error() string {
var message strings.Builder
for _, cause := range v.causes {
if message.Len() > 0 {
_, _ = message.WriteString(causeSeparator)
}
_, _ = message.WriteString(cause.Error())
}
return message.String()
}
func (v *joinedError) Unwrap() []error {
return append([]error(nil), v.causes...)
}
// Cause returns the final error passed to Wrap.
func (v *joinedError) Cause() error {
return v.causes[len(v.causes)-1]
}