blob: 8e59d16cfdaf16257b834ab2e6b5a01dbab413c3 [file] [log] [blame]
Jens Geyer0e87c462013-06-18 22:25:07 +02001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20package thrift
21
22import (
John Boiles57852792018-01-05 14:37:05 -080023 "context"
Jens Geyer0e87c462013-06-18 22:25:07 +020024 "encoding/base64"
25 "fmt"
26)
27
28const (
29 THRIFT_JSON_PROTOCOL_VERSION = 1
30)
31
32// for references to _ParseContext see tsimplejson_protocol.go
33
34// JSON protocol implementation for thrift.
Jens Geyer264a3f32019-02-23 13:11:40 +010035// Utilizes Simple JSON protocol
Jens Geyer0e87c462013-06-18 22:25:07 +020036//
37type TJSONProtocol struct {
38 *TSimpleJSONProtocol
39}
40
41// Constructor
42func NewTJSONProtocol(t TTransport) *TJSONProtocol {
43 v := &TJSONProtocol{TSimpleJSONProtocol: NewTSimpleJSONProtocol(t)}
Yuxuan 'fishy' Wang64c2a4b2020-10-10 18:39:32 -070044 v.parseContextStack.push(_CONTEXT_IN_TOPLEVEL)
45 v.dumpContext.push(_CONTEXT_IN_TOPLEVEL)
Jens Geyer0e87c462013-06-18 22:25:07 +020046 return v
47}
48
49// Factory
50type TJSONProtocolFactory struct{}
51
52func (p *TJSONProtocolFactory) GetProtocol(trans TTransport) TProtocol {
53 return NewTJSONProtocol(trans)
54}
55
56func NewTJSONProtocolFactory() *TJSONProtocolFactory {
57 return &TJSONProtocolFactory{}
58}
59
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070060func (p *TJSONProtocol) WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqId int32) error {
Nobuaki Sukegawa3aa461b2016-04-09 19:46:21 +090061 p.resetContextStack() // THRIFT-3735
Jens Geyer0e87c462013-06-18 22:25:07 +020062 if e := p.OutputListBegin(); e != nil {
63 return e
64 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070065 if e := p.WriteI32(ctx, THRIFT_JSON_PROTOCOL_VERSION); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +020066 return e
67 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070068 if e := p.WriteString(ctx, name); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +020069 return e
70 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070071 if e := p.WriteByte(ctx, int8(typeId)); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +020072 return e
73 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070074 if e := p.WriteI32(ctx, seqId); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +020075 return e
76 }
77 return nil
78}
79
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070080func (p *TJSONProtocol) WriteMessageEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +020081 return p.OutputListEnd()
82}
83
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070084func (p *TJSONProtocol) WriteStructBegin(ctx context.Context, name string) error {
Jens Geyer0e87c462013-06-18 22:25:07 +020085 if e := p.OutputObjectBegin(); e != nil {
86 return e
87 }
88 return nil
89}
90
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070091func (p *TJSONProtocol) WriteStructEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +020092 return p.OutputObjectEnd()
93}
94
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070095func (p *TJSONProtocol) WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error {
96 if e := p.WriteI16(ctx, id); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +020097 return e
98 }
99 if e := p.OutputObjectBegin(); e != nil {
100 return e
101 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200102 s, e1 := p.TypeIdToString(typeId)
103 if e1 != nil {
104 return e1
105 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700106 if e := p.WriteString(ctx, s); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200107 return e
108 }
109 return nil
110}
111
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700112func (p *TJSONProtocol) WriteFieldEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200113 return p.OutputObjectEnd()
114}
115
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700116func (p *TJSONProtocol) WriteFieldStop(ctx context.Context) error { return nil }
Jens Geyer0e87c462013-06-18 22:25:07 +0200117
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700118func (p *TJSONProtocol) WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200119 if e := p.OutputListBegin(); e != nil {
120 return e
121 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200122 s, e1 := p.TypeIdToString(keyType)
123 if e1 != nil {
124 return e1
125 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700126 if e := p.WriteString(ctx, s); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200127 return e
128 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200129 s, e1 = p.TypeIdToString(valueType)
130 if e1 != nil {
131 return e1
132 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700133 if e := p.WriteString(ctx, s); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200134 return e
135 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700136 if e := p.WriteI64(ctx, int64(size)); e != nil {
Jens Geyer0a378702014-12-10 21:04:28 +0100137 return e
138 }
139 return p.OutputObjectBegin()
Jens Geyer0e87c462013-06-18 22:25:07 +0200140}
141
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700142func (p *TJSONProtocol) WriteMapEnd(ctx context.Context) error {
Jens Geyer0a378702014-12-10 21:04:28 +0100143 if e := p.OutputObjectEnd(); e != nil {
144 return e
145 }
Jens Geyer0e87c462013-06-18 22:25:07 +0200146 return p.OutputListEnd()
147}
148
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700149func (p *TJSONProtocol) WriteListBegin(ctx context.Context, elemType TType, size int) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200150 return p.OutputElemListBegin(elemType, size)
151}
152
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700153func (p *TJSONProtocol) WriteListEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200154 return p.OutputListEnd()
155}
156
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700157func (p *TJSONProtocol) WriteSetBegin(ctx context.Context, elemType TType, size int) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200158 return p.OutputElemListBegin(elemType, size)
159}
160
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700161func (p *TJSONProtocol) WriteSetEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200162 return p.OutputListEnd()
163}
164
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700165func (p *TJSONProtocol) WriteBool(ctx context.Context, b bool) error {
Jens Geyerbf3a19d2013-12-17 21:39:30 +0100166 if b {
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700167 return p.WriteI32(ctx, 1)
Jens Geyer2f971e82014-11-18 21:53:17 +0100168 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700169 return p.WriteI32(ctx, 0)
Jens Geyer0e87c462013-06-18 22:25:07 +0200170}
171
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700172func (p *TJSONProtocol) WriteByte(ctx context.Context, b int8) error {
173 return p.WriteI32(ctx, int32(b))
Jens Geyer0e87c462013-06-18 22:25:07 +0200174}
175
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700176func (p *TJSONProtocol) WriteI16(ctx context.Context, v int16) error {
177 return p.WriteI32(ctx, int32(v))
Jens Geyer0e87c462013-06-18 22:25:07 +0200178}
179
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700180func (p *TJSONProtocol) WriteI32(ctx context.Context, v int32) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200181 return p.OutputI64(int64(v))
182}
183
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700184func (p *TJSONProtocol) WriteI64(ctx context.Context, v int64) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200185 return p.OutputI64(int64(v))
186}
187
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700188func (p *TJSONProtocol) WriteDouble(ctx context.Context, v float64) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200189 return p.OutputF64(v)
190}
191
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700192func (p *TJSONProtocol) WriteString(ctx context.Context, v string) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200193 return p.OutputString(v)
194}
195
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700196func (p *TJSONProtocol) WriteBinary(ctx context.Context, v []byte) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200197 // JSON library only takes in a string,
198 // not an arbitrary byte array, to ensure bytes are transmitted
199 // efficiently we must convert this into a valid JSON string
200 // therefore we use base64 encoding to avoid excessive escaping/quoting
201 if e := p.OutputPreValue(); e != nil {
202 return e
203 }
Nobuaki Sukegawa3aa461b2016-04-09 19:46:21 +0900204 if _, e := p.write(JSON_QUOTE_BYTES); e != nil {
Jens Geyer2f971e82014-11-18 21:53:17 +0100205 return NewTProtocolException(e)
206 }
Jens Geyer0e87c462013-06-18 22:25:07 +0200207 writer := base64.NewEncoder(base64.StdEncoding, p.writer)
208 if _, e := writer.Write(v); e != nil {
Nobuaki Sukegawa3aa461b2016-04-09 19:46:21 +0900209 p.writer.Reset(p.trans) // THRIFT-3735
Jens Geyer0e87c462013-06-18 22:25:07 +0200210 return NewTProtocolException(e)
211 }
Jens Geyer2f971e82014-11-18 21:53:17 +0100212 if e := writer.Close(); e != nil {
213 return NewTProtocolException(e)
214 }
Nobuaki Sukegawa3aa461b2016-04-09 19:46:21 +0900215 if _, e := p.write(JSON_QUOTE_BYTES); e != nil {
Jens Geyer2f971e82014-11-18 21:53:17 +0100216 return NewTProtocolException(e)
217 }
Jens Geyer0e87c462013-06-18 22:25:07 +0200218 return p.OutputPostValue()
219}
220
221// Reading methods.
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700222func (p *TJSONProtocol) ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqId int32, err error) {
Nobuaki Sukegawa3aa461b2016-04-09 19:46:21 +0900223 p.resetContextStack() // THRIFT-3735
Jens Geyer0e87c462013-06-18 22:25:07 +0200224 if isNull, err := p.ParseListBegin(); isNull || err != nil {
225 return name, typeId, seqId, err
226 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700227 version, err := p.ReadI32(ctx)
Jens Geyer0e87c462013-06-18 22:25:07 +0200228 if err != nil {
229 return name, typeId, seqId, err
230 }
231 if version != THRIFT_JSON_PROTOCOL_VERSION {
232 e := fmt.Errorf("Unknown Protocol version %d, expected version %d", version, THRIFT_JSON_PROTOCOL_VERSION)
233 return name, typeId, seqId, NewTProtocolExceptionWithType(INVALID_DATA, e)
234
235 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700236 if name, err = p.ReadString(ctx); err != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200237 return name, typeId, seqId, err
238 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700239 bTypeId, err := p.ReadByte(ctx)
Jens Geyer0e87c462013-06-18 22:25:07 +0200240 typeId = TMessageType(bTypeId)
241 if err != nil {
242 return name, typeId, seqId, err
243 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700244 if seqId, err = p.ReadI32(ctx); err != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200245 return name, typeId, seqId, err
246 }
247 return name, typeId, seqId, nil
248}
249
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700250func (p *TJSONProtocol) ReadMessageEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200251 err := p.ParseListEnd()
252 return err
253}
254
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700255func (p *TJSONProtocol) ReadStructBegin(ctx context.Context) (name string, err error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200256 _, err = p.ParseObjectStart()
257 return "", err
258}
259
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700260func (p *TJSONProtocol) ReadStructEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200261 return p.ParseObjectEnd()
262}
263
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700264func (p *TJSONProtocol) ReadFieldBegin(ctx context.Context) (string, TType, int16, error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200265 b, _ := p.reader.Peek(1)
266 if len(b) < 1 || b[0] == JSON_RBRACE[0] || b[0] == JSON_RBRACKET[0] {
267 return "", STOP, -1, nil
268 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700269 fieldId, err := p.ReadI16(ctx)
Jens Geyer0e87c462013-06-18 22:25:07 +0200270 if err != nil {
271 return "", STOP, fieldId, err
272 }
273 if _, err = p.ParseObjectStart(); err != nil {
274 return "", STOP, fieldId, err
275 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700276 sType, err := p.ReadString(ctx)
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200277 if err != nil {
278 return "", STOP, fieldId, err
279 }
280 fType, err := p.StringToTypeId(sType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200281 return "", fType, fieldId, err
282}
283
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700284func (p *TJSONProtocol) ReadFieldEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200285 return p.ParseObjectEnd()
286}
287
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700288func (p *TJSONProtocol) ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, e error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200289 if isNull, e := p.ParseListBegin(); isNull || e != nil {
290 return VOID, VOID, 0, e
291 }
292
293 // read keyType
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700294 sKeyType, e := p.ReadString(ctx)
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200295 if e != nil {
296 return keyType, valueType, size, e
297 }
298 keyType, e = p.StringToTypeId(sKeyType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200299 if e != nil {
300 return keyType, valueType, size, e
301 }
302
303 // read valueType
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700304 sValueType, e := p.ReadString(ctx)
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200305 if e != nil {
306 return keyType, valueType, size, e
307 }
308 valueType, e = p.StringToTypeId(sValueType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200309 if e != nil {
310 return keyType, valueType, size, e
311 }
312
313 // read size
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700314 iSize, e := p.ReadI64(ctx)
Jens Geyer3bb34df2014-12-17 23:06:45 +0100315 if e != nil {
316 return keyType, valueType, size, e
317 }
Jens Geyer0e87c462013-06-18 22:25:07 +0200318 size = int(iSize)
Jens Geyer3bb34df2014-12-17 23:06:45 +0100319
320 _, e = p.ParseObjectStart()
321 return keyType, valueType, size, e
Jens Geyer0e87c462013-06-18 22:25:07 +0200322}
323
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700324func (p *TJSONProtocol) ReadMapEnd(ctx context.Context) error {
Jens Geyer3bb34df2014-12-17 23:06:45 +0100325 e := p.ParseObjectEnd()
326 if e != nil {
327 return e
328 }
Jens Geyer0e87c462013-06-18 22:25:07 +0200329 return p.ParseListEnd()
330}
331
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700332func (p *TJSONProtocol) ReadListBegin(ctx context.Context) (elemType TType, size int, e error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200333 return p.ParseElemListBegin()
334}
335
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700336func (p *TJSONProtocol) ReadListEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200337 return p.ParseListEnd()
338}
339
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700340func (p *TJSONProtocol) ReadSetBegin(ctx context.Context) (elemType TType, size int, e error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200341 return p.ParseElemListBegin()
342}
343
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700344func (p *TJSONProtocol) ReadSetEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200345 return p.ParseListEnd()
346}
347
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700348func (p *TJSONProtocol) ReadBool(ctx context.Context) (bool, error) {
349 value, err := p.ReadI32(ctx)
Jens Geyerbf3a19d2013-12-17 21:39:30 +0100350 return (value != 0), err
Jens Geyer0e87c462013-06-18 22:25:07 +0200351}
352
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700353func (p *TJSONProtocol) ReadByte(ctx context.Context) (int8, error) {
354 v, err := p.ReadI64(ctx)
Jens Geyer5bc8b5a2015-09-05 12:50:24 +0200355 return int8(v), err
Jens Geyer0e87c462013-06-18 22:25:07 +0200356}
357
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700358func (p *TJSONProtocol) ReadI16(ctx context.Context) (int16, error) {
359 v, err := p.ReadI64(ctx)
Jens Geyer0e87c462013-06-18 22:25:07 +0200360 return int16(v), err
361}
362
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700363func (p *TJSONProtocol) ReadI32(ctx context.Context) (int32, error) {
364 v, err := p.ReadI64(ctx)
Jens Geyer0e87c462013-06-18 22:25:07 +0200365 return int32(v), err
366}
367
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700368func (p *TJSONProtocol) ReadI64(ctx context.Context) (int64, error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200369 v, _, err := p.ParseI64()
370 return v, err
371}
372
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700373func (p *TJSONProtocol) ReadDouble(ctx context.Context) (float64, error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200374 v, _, err := p.ParseF64()
375 return v, err
376}
377
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700378func (p *TJSONProtocol) ReadString(ctx context.Context) (string, error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200379 var v string
380 if err := p.ParsePreValue(); err != nil {
381 return v, err
382 }
Jens Geyer2f971e82014-11-18 21:53:17 +0100383 f, _ := p.reader.Peek(1)
384 if len(f) > 0 && f[0] == JSON_QUOTE {
Jens Geyer0e87c462013-06-18 22:25:07 +0200385 p.reader.ReadByte()
386 value, err := p.ParseStringBody()
387 v = value
388 if err != nil {
389 return v, err
390 }
Nobuaki Sukegawa9b936612015-10-10 11:28:54 +0900391 } else if len(f) > 0 && f[0] == JSON_NULL[0] {
Jens Geyer2f971e82014-11-18 21:53:17 +0100392 b := make([]byte, len(JSON_NULL))
393 _, err := p.reader.Read(b)
Jens Geyer0e87c462013-06-18 22:25:07 +0200394 if err != nil {
395 return v, NewTProtocolException(err)
396 }
Jens Geyer2f971e82014-11-18 21:53:17 +0100397 if string(b) != string(JSON_NULL) {
398 e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b))
399 return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
400 }
Jens Geyer0e87c462013-06-18 22:25:07 +0200401 } else {
Jens Geyer2f971e82014-11-18 21:53:17 +0100402 e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f))
Jens Geyer0e87c462013-06-18 22:25:07 +0200403 return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
404 }
405 return v, p.ParsePostValue()
406}
407
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700408func (p *TJSONProtocol) ReadBinary(ctx context.Context) ([]byte, error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200409 var v []byte
410 if err := p.ParsePreValue(); err != nil {
411 return nil, err
412 }
Jens Geyer2f971e82014-11-18 21:53:17 +0100413 f, _ := p.reader.Peek(1)
414 if len(f) > 0 && f[0] == JSON_QUOTE {
Jens Geyer0e87c462013-06-18 22:25:07 +0200415 p.reader.ReadByte()
416 value, err := p.ParseBase64EncodedBody()
417 v = value
418 if err != nil {
419 return v, err
420 }
Nobuaki Sukegawa9b936612015-10-10 11:28:54 +0900421 } else if len(f) > 0 && f[0] == JSON_NULL[0] {
Jens Geyer2f971e82014-11-18 21:53:17 +0100422 b := make([]byte, len(JSON_NULL))
423 _, err := p.reader.Read(b)
Jens Geyer0e87c462013-06-18 22:25:07 +0200424 if err != nil {
425 return v, NewTProtocolException(err)
426 }
Jens Geyer2f971e82014-11-18 21:53:17 +0100427 if string(b) != string(JSON_NULL) {
428 e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b))
429 return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
430 }
Jens Geyer0e87c462013-06-18 22:25:07 +0200431 } else {
Jens Geyer2f971e82014-11-18 21:53:17 +0100432 e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f))
Jens Geyer0e87c462013-06-18 22:25:07 +0200433 return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
434 }
Jens Geyer2f971e82014-11-18 21:53:17 +0100435
Jens Geyer0e87c462013-06-18 22:25:07 +0200436 return v, p.ParsePostValue()
437}
438
John Boiles57852792018-01-05 14:37:05 -0800439func (p *TJSONProtocol) Flush(ctx context.Context) (err error) {
Jens Geyerce8d5182013-12-07 00:08:37 +0100440 err = p.writer.Flush()
441 if err == nil {
John Boiles57852792018-01-05 14:37:05 -0800442 err = p.trans.Flush(ctx)
Jens Geyerce8d5182013-12-07 00:08:37 +0100443 }
444 return NewTProtocolException(err)
Jens Geyer0e87c462013-06-18 22:25:07 +0200445}
446
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700447func (p *TJSONProtocol) Skip(ctx context.Context, fieldType TType) (err error) {
448 return SkipDefaultDepth(ctx, p, fieldType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200449}
450
451func (p *TJSONProtocol) Transport() TTransport {
452 return p.trans
453}
454
455func (p *TJSONProtocol) OutputElemListBegin(elemType TType, size int) error {
456 if e := p.OutputListBegin(); e != nil {
457 return e
458 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200459 s, e1 := p.TypeIdToString(elemType)
460 if e1 != nil {
461 return e1
462 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700463 if e := p.OutputString(s); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200464 return e
465 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700466 if e := p.OutputI64(int64(size)); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200467 return e
468 }
469 return nil
470}
471
Jens Geyer0e87c462013-06-18 22:25:07 +0200472func (p *TJSONProtocol) ParseElemListBegin() (elemType TType, size int, e error) {
473 if isNull, e := p.ParseListBegin(); isNull || e != nil {
474 return VOID, 0, e
475 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700476 // We don't really use the ctx in ReadString implementation,
477 // so this is safe for now.
478 // We might want to add context to ParseElemListBegin if we start to use
479 // ctx in ReadString implementation in the future.
480 sElemType, err := p.ReadString(context.Background())
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200481 if err != nil {
482 return VOID, size, err
483 }
484 elemType, err = p.StringToTypeId(sElemType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200485 if err != nil {
486 return elemType, size, err
487 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700488 nSize, _, err2 := p.ParseI64()
Jens Geyer0e87c462013-06-18 22:25:07 +0200489 size = int(nSize)
490 return elemType, size, err2
491}
492
493func (p *TJSONProtocol) readElemListBegin() (elemType TType, size int, e error) {
494 if isNull, e := p.ParseListBegin(); isNull || e != nil {
495 return VOID, 0, e
496 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700497 // We don't really use the ctx in ReadString implementation,
498 // so this is safe for now.
499 // We might want to add context to ParseElemListBegin if we start to use
500 // ctx in ReadString implementation in the future.
501 sElemType, err := p.ReadString(context.Background())
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200502 if err != nil {
503 return VOID, size, err
504 }
505 elemType, err = p.StringToTypeId(sElemType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200506 if err != nil {
507 return elemType, size, err
508 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700509 nSize, _, err2 := p.ParseI64()
Jens Geyer0e87c462013-06-18 22:25:07 +0200510 size = int(nSize)
511 return elemType, size, err2
512}
513
514func (p *TJSONProtocol) writeElemListBegin(elemType TType, size int) error {
515 if e := p.OutputListBegin(); e != nil {
516 return e
517 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200518 s, e1 := p.TypeIdToString(elemType)
519 if e1 != nil {
520 return e1
521 }
522 if e := p.OutputString(s); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200523 return e
524 }
525 if e := p.OutputI64(int64(size)); e != nil {
526 return e
527 }
528 return nil
529}
530
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200531func (p *TJSONProtocol) TypeIdToString(fieldType TType) (string, error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200532 switch byte(fieldType) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200533 case BOOL:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200534 return "tf", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200535 case BYTE:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200536 return "i8", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200537 case I16:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200538 return "i16", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200539 case I32:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200540 return "i32", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200541 case I64:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200542 return "i64", nil
543 case DOUBLE:
544 return "dbl", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200545 case STRING:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200546 return "str", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200547 case STRUCT:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200548 return "rec", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200549 case MAP:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200550 return "map", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200551 case SET:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200552 return "set", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200553 case LIST:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200554 return "lst", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200555 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200556
557 e := fmt.Errorf("Unknown fieldType: %d", int(fieldType))
558 return "", NewTProtocolExceptionWithType(INVALID_DATA, e)
Jens Geyer0e87c462013-06-18 22:25:07 +0200559}
560
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200561func (p *TJSONProtocol) StringToTypeId(fieldType string) (TType, error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200562 switch fieldType {
Jens Geyer0e87c462013-06-18 22:25:07 +0200563 case "tf":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200564 return TType(BOOL), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200565 case "i8":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200566 return TType(BYTE), nil
567 case "i16":
568 return TType(I16), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200569 case "i32":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200570 return TType(I32), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200571 case "i64":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200572 return TType(I64), nil
573 case "dbl":
574 return TType(DOUBLE), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200575 case "str":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200576 return TType(STRING), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200577 case "rec":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200578 return TType(STRUCT), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200579 case "map":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200580 return TType(MAP), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200581 case "set":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200582 return TType(SET), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200583 case "lst":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200584 return TType(LIST), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200585 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200586
587 e := fmt.Errorf("Unknown type identifier: %s", fieldType)
588 return TType(STOP), NewTProtocolExceptionWithType(INVALID_DATA, e)
Jens Geyer0e87c462013-06-18 22:25:07 +0200589}
Yuxuan 'fishy' Wangc4d1c0d2020-12-16 17:10:48 -0800590
591var _ TConfigurationSetter = (*TJSONProtocol)(nil)