-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathcodec.go
More file actions
188 lines (167 loc) · 4.08 KB
/
Copy pathcodec.go
File metadata and controls
188 lines (167 loc) · 4.08 KB
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
package hasaki
import (
"bytes"
"encoding/xml"
jsoniter "github.com/json-iterator/go"
"github.com/lxzan/hasaki/internal"
"github.com/pkg/errors"
"github.com/valyala/bytebufferpool"
"io"
"net/url"
"strings"
)
const (
// MimeJson JSON MIME类型
// JSON MIME type
MimeJson = "application/json;charset=utf-8"
// MimeYaml YAML MIME类型
// YAML MIME type
MimeYaml = "application/x-yaml;charset=utf-8"
// MimeXml XML MIME类型
// XML MIME type
MimeXml = "application/xml;charset=utf-8"
// MimeProtoBuf Protobuf MIME类型
// Protobuf MIME type
MimeProtoBuf = "application/x-protobuf"
// MimeForm 表单 MIME类型
// Form MIME type
MimeForm = "application/x-www-form-urlencoded"
// MimeStream 流式 MIME类型
// Stream MIME type
MimeStream = "application/octet-stream"
// MimeJpeg JPEG图片 MIME类型
// JPEG image MIME type
MimeJpeg = "image/jpeg"
// MimeGif GIF图片 MIME类型
// GIF image MIME type
MimeGif = "image/gif"
// MimePng PNG图片 MIME类型
// PNG image MIME type
MimePng = "image/png"
// MimeMp4 MP4视频 MIME类型
// MP4 video MIME type
MimeMp4 = "video/mpeg4"
)
// Any 通用类型映射
// Generic type map
type Any map[string]any
type (
// Codec 编解码器接口,同时包含编码和解码功能
// Codec interface, includes both encoding and decoding functionality
Codec interface {
Encoder
Decoder
}
// Encoder 编码器接口
// Encoder interface
Encoder interface {
Encode(v any) (io.Reader, error)
ContentType() string
}
// Decoder 解码器接口
// Decoder interface
Decoder interface {
Decode(r io.Reader, v any) error
}
)
var (
// JsonCodec JSON编解码器
// JSON codec
JsonCodec = new(jsonCodec)
// FormCodec 表单编解码器
// Form codec
FormCodec = new(formCodec)
// XmlCodec XML编解码器
// XML codec
XmlCodec = new(xmlCodec)
)
type (
jsonCodec struct{}
formCodec struct{}
xmlCodec struct{}
)
func (c jsonCodec) Encode(v any) (io.Reader, error) {
if v == nil {
return nil, nil
}
w := bytebufferpool.Get()
err := jsoniter.ConfigFastest.NewEncoder(w).Encode(v)
r := &internal.CloserWrapper{B: w, R: bytes.NewReader(w.B)}
return r, errors.WithStack(err)
}
func (c jsonCodec) ContentType() string {
return MimeJson
}
func (c jsonCodec) Decode(r io.Reader, v any) error {
return jsoniter.ConfigFastest.NewDecoder(r).Decode(v)
}
func (f formCodec) Encode(v any) (io.Reader, error) {
if v == nil {
return nil, nil
}
switch r := v.(type) {
case url.Values:
return strings.NewReader(r.Encode()), nil
case string:
return strings.NewReader(r), nil
default:
return nil, errors.WithStack(errUnsupportedData)
}
}
func (f formCodec) ContentType() string {
return MimeForm
}
func (f formCodec) Decode(r io.Reader, v any) error {
values, ok := v.(*url.Values)
if !ok {
return errors.Wrap(errUnsupportedData, "v must be *url.Values type")
}
var builder = &strings.Builder{}
var temp = internal.GetBuffer()
_, _ = io.CopyBuffer(builder, r, temp.Bytes()[:internal.BufferSize])
internal.PutBuffer(temp)
result, err := url.ParseQuery(builder.String())
if err != nil {
return errors.WithStack(err)
}
*values = result
return nil
}
func (c xmlCodec) Encode(v any) (io.Reader, error) {
if v == nil {
return nil, nil
}
w := bytebufferpool.Get()
err := xml.NewEncoder(w).Encode(v)
r := &internal.CloserWrapper{B: w, R: bytes.NewReader(w.B)}
return r, errors.WithStack(err)
}
func (c xmlCodec) ContentType() string {
return MimeXml
}
func (c xmlCodec) Decode(r io.Reader, v any) error {
return errors.WithStack(xml.NewDecoder(r).Decode(v))
}
type streamEncoder struct {
contentType string
}
// NewStreamEncoder 创建流式编码器
// Create a stream encoder
func NewStreamEncoder(contentType string) Encoder {
return &streamEncoder{contentType: contentType}
}
func (c *streamEncoder) Encode(v any) (io.Reader, error) {
switch r := v.(type) {
case io.Reader:
return r, nil
case []byte:
return bytes.NewReader(r), nil
case string:
return strings.NewReader(r), nil
default:
return nil, errors.WithStack(errUnsupportedData)
}
}
func (c *streamEncoder) ContentType() string {
return c.contentType
}