forked from OneOfOne/gserv
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcodecs.go
127 lines (102 loc) · 2.56 KB
/
codecs.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package gserv
import (
"encoding/json"
"fmt"
"io"
"net/http"
"github.com/alpineiq/genh"
)
// Common mime-types
const (
MimeJSON = "application/json"
MimeEvent = "text/event-stream"
MimeMsgPack = "application/msgpack"
MimeXML = "application/xml"
MimeJavascript = "application/javascript"
MimeHTML = "text/html"
MimePlain = "text/plain"
MimeBinary = "application/octet-stream"
)
var (
_ Codec = (*PlainTextCodec)(nil)
_ Codec = (*JSONCodec)(nil)
_ Codec = (*MsgpCodec)(nil)
_ Codec = (*MixedCodec[JSONCodec, MsgpCodec])(nil)
)
type Encoder interface {
Encode(v any) error
}
type Decoder interface {
Decode(v any) error
}
type Codec interface {
ContentType() string
Decode(r io.Reader, body any) error
Encode(w io.Writer, v any) error
}
type PlainTextCodec struct{}
func (PlainTextCodec) ContentType() string { return "" }
func (PlainTextCodec) Decode(r io.Reader, out any) error {
b, err := io.ReadAll(r)
switch out := out.(type) {
case *string:
*out = string(b)
case *[]byte:
*out = b
case io.Writer:
_, err = out.Write(b)
default:
return fmt.Errorf("%T is not a valid type for PlainTextCodec", out)
}
return err
}
func (PlainTextCodec) Encode(w io.Writer, v any) (err2 error) {
switch v := v.(type) {
case string:
_, err2 = io.WriteString(w, v)
case []byte:
_, err2 = w.Write(v)
case io.Reader:
_, err2 = io.Copy(w, v)
default:
return fmt.Errorf("%T is not a valid type for PlainTextCodec", v)
}
return
}
type JSONCodec struct{ Indent bool }
func (JSONCodec) ContentType() string { return MimeJSON }
func (JSONCodec) Decode(r io.Reader, out any) error {
return json.NewDecoder(r).Decode(&out)
}
func (j JSONCodec) Encode(w io.Writer, v any) error {
enc := json.NewEncoder(w)
if j.Indent {
enc.SetIndent("", "\t")
}
return enc.Encode(v)
}
type MsgpCodec struct{}
func (MsgpCodec) ContentType() string { return MimeMsgPack }
func (MsgpCodec) Decode(r io.Reader, out any) error {
return genh.DecodeMsgpack(r, out)
}
func (c MsgpCodec) Encode(w io.Writer, v any) error {
return genh.EncodeMsgpack(w, v)
}
type MixedCodec[Dec, Enc Codec] struct {
dec Dec
enc Enc
}
func (m MixedCodec[Dec, Enc]) ContentType() string { return m.enc.ContentType() }
func (m MixedCodec[Dec, Enc]) Decode(r io.Reader, out any) error {
return m.dec.Decode(r, out)
}
func (m MixedCodec[Dec, Enc]) Encode(w io.Writer, v any) error {
return m.enc.Encode(w, v)
}
func getError(err error) HTTPError {
if err, ok := err.(HTTPError); ok {
return err
}
return &Error{Code: http.StatusBadRequest, Message: err.Error()}
}