Source file
src/errors/wrap.go
1
2
3
4
5 package errors
6
7 import (
8 "internal/reflectlite"
9 )
10
11
12
13
14
15
16
17 func Unwrap(err error) error {
18 u, ok := err.(interface {
19 Unwrap() error
20 })
21 if !ok {
22 return nil
23 }
24 return u.Unwrap()
25 }
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 func Is(err, target error) bool {
45 if err == nil || target == nil {
46 return err == target
47 }
48
49 isComparable := reflectlite.TypeOf(target).Comparable()
50 return is(err, target, isComparable)
51 }
52
53 func is(err, target error, targetComparable bool) bool {
54 for {
55 if targetComparable && err == target {
56 return true
57 }
58 if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {
59 return true
60 }
61 switch x := err.(type) {
62 case interface{ Unwrap() error }:
63 err = x.Unwrap()
64 if err == nil {
65 return false
66 }
67 case interface{ Unwrap() []error }:
68 for _, err := range x.Unwrap() {
69 if is(err, target, targetComparable) {
70 return true
71 }
72 }
73 return false
74 default:
75 return false
76 }
77 }
78 }
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 func As(err error, target any) bool {
98 if err == nil {
99 return false
100 }
101 if target == nil {
102 panic("errors: target cannot be nil")
103 }
104 val := reflectlite.ValueOf(target)
105 typ := val.Type()
106 if typ.Kind() != reflectlite.Ptr || val.IsNil() {
107 panic("errors: target must be a non-nil pointer")
108 }
109 targetType := typ.Elem()
110 if targetType.Kind() != reflectlite.Interface && !targetType.Implements(errorType) {
111 panic("errors: *target must be interface or implement error")
112 }
113 return as(err, target, val, targetType)
114 }
115
116 func as(err error, target any, targetVal reflectlite.Value, targetType reflectlite.Type) bool {
117 for {
118 if reflectlite.TypeOf(err).AssignableTo(targetType) {
119 targetVal.Elem().Set(reflectlite.ValueOf(err))
120 return true
121 }
122 if x, ok := err.(interface{ As(any) bool }); ok && x.As(target) {
123 return true
124 }
125 switch x := err.(type) {
126 case interface{ Unwrap() error }:
127 err = x.Unwrap()
128 if err == nil {
129 return false
130 }
131 case interface{ Unwrap() []error }:
132 for _, err := range x.Unwrap() {
133 if err == nil {
134 continue
135 }
136 if as(err, target, targetVal, targetType) {
137 return true
138 }
139 }
140 return false
141 default:
142 return false
143 }
144 }
145 }
146
147 var errorType = reflectlite.TypeOf((*error)(nil)).Elem()
148
View as plain text