...
1 package emperror
2
3 import (
4 "fmt"
5 "io"
6 "runtime"
7
8 "github.com/pkg/errors"
9 )
10
11 func callers() []uintptr {
12 const depth = 32
13 var pcs [depth]uintptr
14
15 n := runtime.Callers(3, pcs[:])
16
17 return pcs[0:n]
18 }
19
20 type wrappedError struct {
21 err error
22 stack []uintptr
23 }
24
25 func (e *wrappedError) Error() string {
26 return e.err.Error()
27 }
28
29 func (e *wrappedError) Cause() error {
30 return e.err
31 }
32
33 func (e *wrappedError) StackTrace() errors.StackTrace {
34 f := make([]errors.Frame, len(e.stack))
35
36 for i := 0; i < len(f); i++ {
37 f[i] = errors.Frame((e.stack)[i])
38 }
39
40 return f
41 }
42
43 func (e *wrappedError) Format(s fmt.State, verb rune) {
44 switch verb {
45 case 'v':
46 if s.Flag('+') {
47 _, _ = fmt.Fprintf(s, "%+v", e.Cause())
48
49 for _, pc := range e.stack {
50 f := errors.Frame(pc)
51 _, _ = fmt.Fprintf(s, "\n%+v", f)
52 }
53
54 return
55 }
56
57 fallthrough
58
59 case 's':
60 _, _ = io.WriteString(s, e.Error())
61
62 case 'q':
63 _, _ = fmt.Fprintf(s, "%q", e.Error())
64 }
65 }
66
67
68
69
70
71
72 func Wrap(err error, message string) error {
73 if err == nil {
74 return nil
75 }
76
77 _, ok := getStackTracer(err)
78
79 err = errors.WithMessage(err, message)
80
81
82 if !ok {
83 err = &wrappedError{
84 err: err,
85 stack: callers(),
86 }
87 }
88
89 return err
90 }
91
92
93
94
95
96
97 func Wrapf(err error, format string, args ...interface{}) error {
98 if err == nil {
99 return nil
100 }
101
102 _, ok := getStackTracer(err)
103
104 err = errors.WithMessage(err, fmt.Sprintf(format, args...))
105
106
107 if !ok {
108 err = &wrappedError{
109 err: err,
110 stack: callers(),
111 }
112 }
113
114 return err
115 }
116
View as plain text