1
2
3
4
5 package xerrors
6
7 import (
8 "reflect"
9 )
10
11
12 type Wrapper interface {
13
14
15 Unwrap() error
16 }
17
18
19
20 func Opaque(err error) error {
21 return noWrapper{err}
22 }
23
24 type noWrapper struct {
25 error
26 }
27
28 func (e noWrapper) FormatError(p Printer) (next error) {
29 if f, ok := e.error.(Formatter); ok {
30 return f.FormatError(p)
31 }
32 p.Print(e.error)
33 return nil
34 }
35
36
37
38 func Unwrap(err error) error {
39 u, ok := err.(Wrapper)
40 if !ok {
41 return nil
42 }
43 return u.Unwrap()
44 }
45
46
47
48
49
50 func Is(err, target error) bool {
51 if target == nil {
52 return err == target
53 }
54
55 isComparable := reflect.TypeOf(target).Comparable()
56 for {
57 if isComparable && err == target {
58 return true
59 }
60 if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {
61 return true
62 }
63
64
65
66 if err = Unwrap(err); err == nil {
67 return false
68 }
69 }
70 }
71
72
73
74
75
76
77
78
79
80 func As(err error, target interface{}) bool {
81 if target == nil {
82 panic("errors: target cannot be nil")
83 }
84 val := reflect.ValueOf(target)
85 typ := val.Type()
86 if typ.Kind() != reflect.Ptr || val.IsNil() {
87 panic("errors: target must be a non-nil pointer")
88 }
89 if e := typ.Elem(); e.Kind() != reflect.Interface && !e.Implements(errorType) {
90 panic("errors: *target must be interface or implement error")
91 }
92 targetType := typ.Elem()
93 for err != nil {
94 if reflect.TypeOf(err).AssignableTo(targetType) {
95 val.Elem().Set(reflect.ValueOf(err))
96 return true
97 }
98 if x, ok := err.(interface{ As(interface{}) bool }); ok && x.As(target) {
99 return true
100 }
101 err = Unwrap(err)
102 }
103 return false
104 }
105
106 var errorType = reflect.TypeOf((*error)(nil)).Elem()
107
View as plain text