-
Notifications
You must be signed in to change notification settings - Fork 1
/
rd_err.go
112 lines (92 loc) · 2.46 KB
/
rd_err.go
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
package rd
import (
"fmt"
"io"
"net/http"
r "reflect"
"strconv"
)
/*
Wraps another error, adding an HTTP status code. Some errors returned by this
package are wrapped with codes such as 400 and 500.
*/
type Err struct {
Status int `json:"status"`
Cause error `json:"cause"`
}
// Implement a hidden interface in "errors".
func (self Err) Unwrap() error { return self.Cause }
// Returns `.Status`. Implements a hidden interface supported by
// `github.com/mitranim/rout`.
func (self Err) HttpStatusCode() int { return self.Status }
// Implement the `error` interface.
func (self Err) Error() string { return bytesString(self.AppendTo(nil)) }
// Appends the error representation. Used internally by `.Error`.
func (self Err) AppendTo(buf []byte) []byte {
buf = append(buf, `[rd] error`...)
if self.Status != 0 {
buf = append(buf, ` (HTTP status `...)
buf = strconv.AppendInt(buf, int64(self.Status), 10)
buf = append(buf, `)`...)
}
cause := self.Cause
if cause != nil {
buf = append(buf, `: `...)
impl, _ := cause.(interface{ AppendTo([]byte) []byte })
if impl != nil {
buf = impl.AppendTo(buf)
} else {
buf = append(buf, cause.Error()...)
}
}
return buf
}
// Implement `fmt.Formatter`.
func (self Err) Format(out fmt.State, verb rune) {
if out.Flag('+') {
msg := self.AppendTo(nil)
_, _ = out.Write(msg)
if self.Cause != nil {
if len(msg) > 0 {
_, _ = io.WriteString(out, "\ncause:\n")
}
fmt.Fprintf(out, `%+v`, self.Cause)
}
return
}
if out.Flag('#') {
type Error Err
fmt.Fprintf(out, `%#v`, Error(self))
return
}
_, _ = out.Write(self.AppendTo(nil))
}
func errBadReq(err error) error {
if err == nil {
return nil
}
return Err{http.StatusBadRequest, err}
}
func errInternal(err error) error {
if err == nil {
return nil
}
return Err{http.StatusInternalServerError, err}
}
func errInvalidPtr(val r.Value) error {
return errInternal(fmt.Errorf(`expected settable struct pointer, got %v`, val))
}
func errParse(err error, input string, out r.Type) error {
if err == nil {
return nil
}
return fmt.Errorf(`failed to parse %q into %v: %v`, input, out, err)
}
func errContentType(typ string) error {
if typ == `` {
return errBadReq(fmt.Errorf(`missing content type`))
}
return errBadReq(fmt.Errorf(`unsupported content type %q`, typ))
}
var errJsonEof = errInternal(fmt.Errorf(`unexpected %w during JSON decoding`, io.EOF))
var errUnreachable = errInternal(fmt.Errorf(`unexpected violation of internal invariant`))