blob: 3d53b698d809245253f4a6b20e83c1c8580cfb0a [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 +020036type TJSONProtocol struct {
37 *TSimpleJSONProtocol
38}
39
40// Constructor
41func NewTJSONProtocol(t TTransport) *TJSONProtocol {
42 v := &TJSONProtocol{TSimpleJSONProtocol: NewTSimpleJSONProtocol(t)}
Yuxuan 'fishy' Wang64c2a4b2020-10-10 18:39:32 -070043 v.parseContextStack.push(_CONTEXT_IN_TOPLEVEL)
44 v.dumpContext.push(_CONTEXT_IN_TOPLEVEL)
Jens Geyer0e87c462013-06-18 22:25:07 +020045 return v
46}
47
48// Factory
49type TJSONProtocolFactory struct{}
50
51func (p *TJSONProtocolFactory) GetProtocol(trans TTransport) TProtocol {
52 return NewTJSONProtocol(trans)
53}
54
55func NewTJSONProtocolFactory() *TJSONProtocolFactory {
56 return &TJSONProtocolFactory{}
57}
58
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070059func (p *TJSONProtocol) WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqId int32) error {
Nobuaki Sukegawa3aa461b2016-04-09 19:46:21 +090060 p.resetContextStack() // THRIFT-3735
Jens Geyer0e87c462013-06-18 22:25:07 +020061 if e := p.OutputListBegin(); e != nil {
62 return e
63 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070064 if e := p.WriteI32(ctx, THRIFT_JSON_PROTOCOL_VERSION); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +020065 return e
66 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070067 if e := p.WriteString(ctx, name); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +020068 return e
69 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070070 if e := p.WriteByte(ctx, int8(typeId)); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +020071 return e
72 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070073 if e := p.WriteI32(ctx, seqId); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +020074 return e
75 }
76 return nil
77}
78
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070079func (p *TJSONProtocol) WriteMessageEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +020080 return p.OutputListEnd()
81}
82
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070083func (p *TJSONProtocol) WriteStructBegin(ctx context.Context, name string) error {
Jens Geyer0e87c462013-06-18 22:25:07 +020084 if e := p.OutputObjectBegin(); e != nil {
85 return e
86 }
87 return nil
88}
89
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070090func (p *TJSONProtocol) WriteStructEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +020091 return p.OutputObjectEnd()
92}
93
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -070094func (p *TJSONProtocol) WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error {
95 if e := p.WriteI16(ctx, id); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +020096 return e
97 }
98 if e := p.OutputObjectBegin(); e != nil {
99 return e
100 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200101 s, e1 := p.TypeIdToString(typeId)
102 if e1 != nil {
103 return e1
104 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700105 if e := p.WriteString(ctx, s); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200106 return e
107 }
108 return nil
109}
110
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700111func (p *TJSONProtocol) WriteFieldEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200112 return p.OutputObjectEnd()
113}
114
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700115func (p *TJSONProtocol) WriteFieldStop(ctx context.Context) error { return nil }
Jens Geyer0e87c462013-06-18 22:25:07 +0200116
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700117func (p *TJSONProtocol) WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200118 if e := p.OutputListBegin(); e != nil {
119 return e
120 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200121 s, e1 := p.TypeIdToString(keyType)
122 if e1 != nil {
123 return e1
124 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700125 if e := p.WriteString(ctx, s); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200126 return e
127 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200128 s, e1 = p.TypeIdToString(valueType)
129 if e1 != nil {
130 return e1
131 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700132 if e := p.WriteString(ctx, s); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200133 return e
134 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700135 if e := p.WriteI64(ctx, int64(size)); e != nil {
Jens Geyer0a378702014-12-10 21:04:28 +0100136 return e
137 }
138 return p.OutputObjectBegin()
Jens Geyer0e87c462013-06-18 22:25:07 +0200139}
140
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700141func (p *TJSONProtocol) WriteMapEnd(ctx context.Context) error {
Jens Geyer0a378702014-12-10 21:04:28 +0100142 if e := p.OutputObjectEnd(); e != nil {
143 return e
144 }
Jens Geyer0e87c462013-06-18 22:25:07 +0200145 return p.OutputListEnd()
146}
147
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700148func (p *TJSONProtocol) WriteListBegin(ctx context.Context, elemType TType, size int) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200149 return p.OutputElemListBegin(elemType, size)
150}
151
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700152func (p *TJSONProtocol) WriteListEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200153 return p.OutputListEnd()
154}
155
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700156func (p *TJSONProtocol) WriteSetBegin(ctx context.Context, elemType TType, size int) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200157 return p.OutputElemListBegin(elemType, size)
158}
159
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700160func (p *TJSONProtocol) WriteSetEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200161 return p.OutputListEnd()
162}
163
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700164func (p *TJSONProtocol) WriteBool(ctx context.Context, b bool) error {
Jens Geyerbf3a19d2013-12-17 21:39:30 +0100165 if b {
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700166 return p.WriteI32(ctx, 1)
Jens Geyer2f971e82014-11-18 21:53:17 +0100167 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700168 return p.WriteI32(ctx, 0)
Jens Geyer0e87c462013-06-18 22:25:07 +0200169}
170
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700171func (p *TJSONProtocol) WriteByte(ctx context.Context, b int8) error {
172 return p.WriteI32(ctx, int32(b))
Jens Geyer0e87c462013-06-18 22:25:07 +0200173}
174
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700175func (p *TJSONProtocol) WriteI16(ctx context.Context, v int16) error {
176 return p.WriteI32(ctx, int32(v))
Jens Geyer0e87c462013-06-18 22:25:07 +0200177}
178
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700179func (p *TJSONProtocol) WriteI32(ctx context.Context, v int32) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200180 return p.OutputI64(int64(v))
181}
182
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700183func (p *TJSONProtocol) WriteI64(ctx context.Context, v int64) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200184 return p.OutputI64(int64(v))
185}
186
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700187func (p *TJSONProtocol) WriteDouble(ctx context.Context, v float64) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200188 return p.OutputF64(v)
189}
190
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700191func (p *TJSONProtocol) WriteString(ctx context.Context, v string) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200192 return p.OutputString(v)
193}
194
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700195func (p *TJSONProtocol) WriteBinary(ctx context.Context, v []byte) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200196 // JSON library only takes in a string,
197 // not an arbitrary byte array, to ensure bytes are transmitted
198 // efficiently we must convert this into a valid JSON string
199 // therefore we use base64 encoding to avoid excessive escaping/quoting
200 if e := p.OutputPreValue(); e != nil {
201 return e
202 }
Nobuaki Sukegawa3aa461b2016-04-09 19:46:21 +0900203 if _, e := p.write(JSON_QUOTE_BYTES); e != nil {
Jens Geyer2f971e82014-11-18 21:53:17 +0100204 return NewTProtocolException(e)
205 }
Jens Geyer0e87c462013-06-18 22:25:07 +0200206 writer := base64.NewEncoder(base64.StdEncoding, p.writer)
207 if _, e := writer.Write(v); e != nil {
Nobuaki Sukegawa3aa461b2016-04-09 19:46:21 +0900208 p.writer.Reset(p.trans) // THRIFT-3735
Jens Geyer0e87c462013-06-18 22:25:07 +0200209 return NewTProtocolException(e)
210 }
Jens Geyer2f971e82014-11-18 21:53:17 +0100211 if e := writer.Close(); e != nil {
212 return NewTProtocolException(e)
213 }
Nobuaki Sukegawa3aa461b2016-04-09 19:46:21 +0900214 if _, e := p.write(JSON_QUOTE_BYTES); e != nil {
Jens Geyer2f971e82014-11-18 21:53:17 +0100215 return NewTProtocolException(e)
216 }
Jens Geyer0e87c462013-06-18 22:25:07 +0200217 return p.OutputPostValue()
218}
219
220// Reading methods.
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700221func (p *TJSONProtocol) ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqId int32, err error) {
Nobuaki Sukegawa3aa461b2016-04-09 19:46:21 +0900222 p.resetContextStack() // THRIFT-3735
Jens Geyer0e87c462013-06-18 22:25:07 +0200223 if isNull, err := p.ParseListBegin(); isNull || err != nil {
224 return name, typeId, seqId, err
225 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700226 version, err := p.ReadI32(ctx)
Jens Geyer0e87c462013-06-18 22:25:07 +0200227 if err != nil {
228 return name, typeId, seqId, err
229 }
230 if version != THRIFT_JSON_PROTOCOL_VERSION {
231 e := fmt.Errorf("Unknown Protocol version %d, expected version %d", version, THRIFT_JSON_PROTOCOL_VERSION)
232 return name, typeId, seqId, NewTProtocolExceptionWithType(INVALID_DATA, e)
233
234 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700235 if name, err = p.ReadString(ctx); err != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200236 return name, typeId, seqId, err
237 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700238 bTypeId, err := p.ReadByte(ctx)
Jens Geyer0e87c462013-06-18 22:25:07 +0200239 typeId = TMessageType(bTypeId)
240 if err != nil {
241 return name, typeId, seqId, err
242 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700243 if seqId, err = p.ReadI32(ctx); err != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200244 return name, typeId, seqId, err
245 }
246 return name, typeId, seqId, nil
247}
248
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700249func (p *TJSONProtocol) ReadMessageEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200250 err := p.ParseListEnd()
251 return err
252}
253
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700254func (p *TJSONProtocol) ReadStructBegin(ctx context.Context) (name string, err error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200255 _, err = p.ParseObjectStart()
256 return "", err
257}
258
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700259func (p *TJSONProtocol) ReadStructEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200260 return p.ParseObjectEnd()
261}
262
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700263func (p *TJSONProtocol) ReadFieldBegin(ctx context.Context) (string, TType, int16, error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200264 b, _ := p.reader.Peek(1)
265 if len(b) < 1 || b[0] == JSON_RBRACE[0] || b[0] == JSON_RBRACKET[0] {
266 return "", STOP, -1, nil
267 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700268 fieldId, err := p.ReadI16(ctx)
Jens Geyer0e87c462013-06-18 22:25:07 +0200269 if err != nil {
270 return "", STOP, fieldId, err
271 }
272 if _, err = p.ParseObjectStart(); err != nil {
273 return "", STOP, fieldId, err
274 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700275 sType, err := p.ReadString(ctx)
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200276 if err != nil {
277 return "", STOP, fieldId, err
278 }
279 fType, err := p.StringToTypeId(sType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200280 return "", fType, fieldId, err
281}
282
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700283func (p *TJSONProtocol) ReadFieldEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200284 return p.ParseObjectEnd()
285}
286
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700287func (p *TJSONProtocol) ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, e error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200288 if isNull, e := p.ParseListBegin(); isNull || e != nil {
289 return VOID, VOID, 0, e
290 }
291
292 // read keyType
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700293 sKeyType, e := p.ReadString(ctx)
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200294 if e != nil {
295 return keyType, valueType, size, e
296 }
297 keyType, e = p.StringToTypeId(sKeyType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200298 if e != nil {
299 return keyType, valueType, size, e
300 }
301
302 // read valueType
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700303 sValueType, e := p.ReadString(ctx)
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200304 if e != nil {
305 return keyType, valueType, size, e
306 }
307 valueType, e = p.StringToTypeId(sValueType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200308 if e != nil {
309 return keyType, valueType, size, e
310 }
311
312 // read size
Yuxuan 'fishy' Wang6583f4e2021-03-25 17:00:31 -0700313 iSize, err := p.ReadI64(ctx)
314 if err != nil {
315 return keyType, valueType, size, err
316 }
Hasnain Lakhani845a87a2025-05-27 22:31:42 -0700317 size = int(iSize)
318
319 minElemSize := p.getMinSerializedSize(keyType) + p.getMinSerializedSize(valueType)
320 totalMinSize := int32(iSize) * minElemSize
321 err = checkSizeForProtocol(totalMinSize, p.cfg)
Yuxuan 'fishy' Wang6583f4e2021-03-25 17:00:31 -0700322 if err != nil {
323 return keyType, valueType, 0, err
Jens Geyer3bb34df2014-12-17 23:06:45 +0100324 }
Jens Geyer3bb34df2014-12-17 23:06:45 +0100325
326 _, e = p.ParseObjectStart()
327 return keyType, valueType, size, e
Jens Geyer0e87c462013-06-18 22:25:07 +0200328}
329
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700330func (p *TJSONProtocol) ReadMapEnd(ctx context.Context) error {
Jens Geyer3bb34df2014-12-17 23:06:45 +0100331 e := p.ParseObjectEnd()
332 if e != nil {
333 return e
334 }
Jens Geyer0e87c462013-06-18 22:25:07 +0200335 return p.ParseListEnd()
336}
337
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700338func (p *TJSONProtocol) ReadListBegin(ctx context.Context) (elemType TType, size int, e error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200339 return p.ParseElemListBegin()
340}
341
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700342func (p *TJSONProtocol) ReadListEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200343 return p.ParseListEnd()
344}
345
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700346func (p *TJSONProtocol) ReadSetBegin(ctx context.Context) (elemType TType, size int, e error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200347 return p.ParseElemListBegin()
348}
349
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700350func (p *TJSONProtocol) ReadSetEnd(ctx context.Context) error {
Jens Geyer0e87c462013-06-18 22:25:07 +0200351 return p.ParseListEnd()
352}
353
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700354func (p *TJSONProtocol) ReadBool(ctx context.Context) (bool, error) {
355 value, err := p.ReadI32(ctx)
Jens Geyerbf3a19d2013-12-17 21:39:30 +0100356 return (value != 0), err
Jens Geyer0e87c462013-06-18 22:25:07 +0200357}
358
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700359func (p *TJSONProtocol) ReadByte(ctx context.Context) (int8, error) {
360 v, err := p.ReadI64(ctx)
Jens Geyer5bc8b5a2015-09-05 12:50:24 +0200361 return int8(v), err
Jens Geyer0e87c462013-06-18 22:25:07 +0200362}
363
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700364func (p *TJSONProtocol) ReadI16(ctx context.Context) (int16, error) {
365 v, err := p.ReadI64(ctx)
Jens Geyer0e87c462013-06-18 22:25:07 +0200366 return int16(v), err
367}
368
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700369func (p *TJSONProtocol) ReadI32(ctx context.Context) (int32, error) {
370 v, err := p.ReadI64(ctx)
Jens Geyer0e87c462013-06-18 22:25:07 +0200371 return int32(v), err
372}
373
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700374func (p *TJSONProtocol) ReadI64(ctx context.Context) (int64, error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200375 v, _, err := p.ParseI64()
376 return v, err
377}
378
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700379func (p *TJSONProtocol) ReadDouble(ctx context.Context) (float64, error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200380 v, _, err := p.ParseF64()
381 return v, err
382}
383
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700384func (p *TJSONProtocol) ReadString(ctx context.Context) (string, error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200385 var v string
386 if err := p.ParsePreValue(); err != nil {
387 return v, err
388 }
Jens Geyer2f971e82014-11-18 21:53:17 +0100389 f, _ := p.reader.Peek(1)
390 if len(f) > 0 && f[0] == JSON_QUOTE {
Jens Geyer0e87c462013-06-18 22:25:07 +0200391 p.reader.ReadByte()
392 value, err := p.ParseStringBody()
393 v = value
394 if err != nil {
395 return v, err
396 }
Nobuaki Sukegawa9b936612015-10-10 11:28:54 +0900397 } else if len(f) > 0 && f[0] == JSON_NULL[0] {
Jens Geyer2f971e82014-11-18 21:53:17 +0100398 b := make([]byte, len(JSON_NULL))
399 _, err := p.reader.Read(b)
Jens Geyer0e87c462013-06-18 22:25:07 +0200400 if err != nil {
401 return v, NewTProtocolException(err)
402 }
Jens Geyer2f971e82014-11-18 21:53:17 +0100403 if string(b) != string(JSON_NULL) {
404 e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b))
405 return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
406 }
Jens Geyer0e87c462013-06-18 22:25:07 +0200407 } else {
Jens Geyer2f971e82014-11-18 21:53:17 +0100408 e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f))
Jens Geyer0e87c462013-06-18 22:25:07 +0200409 return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
410 }
411 return v, p.ParsePostValue()
412}
413
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700414func (p *TJSONProtocol) ReadBinary(ctx context.Context) ([]byte, error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200415 var v []byte
416 if err := p.ParsePreValue(); err != nil {
417 return nil, err
418 }
Jens Geyer2f971e82014-11-18 21:53:17 +0100419 f, _ := p.reader.Peek(1)
420 if len(f) > 0 && f[0] == JSON_QUOTE {
Jens Geyer0e87c462013-06-18 22:25:07 +0200421 p.reader.ReadByte()
422 value, err := p.ParseBase64EncodedBody()
423 v = value
424 if err != nil {
425 return v, err
426 }
Nobuaki Sukegawa9b936612015-10-10 11:28:54 +0900427 } else if len(f) > 0 && f[0] == JSON_NULL[0] {
Jens Geyer2f971e82014-11-18 21:53:17 +0100428 b := make([]byte, len(JSON_NULL))
429 _, err := p.reader.Read(b)
Jens Geyer0e87c462013-06-18 22:25:07 +0200430 if err != nil {
431 return v, NewTProtocolException(err)
432 }
Jens Geyer2f971e82014-11-18 21:53:17 +0100433 if string(b) != string(JSON_NULL) {
434 e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b))
435 return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
436 }
Jens Geyer0e87c462013-06-18 22:25:07 +0200437 } else {
Jens Geyer2f971e82014-11-18 21:53:17 +0100438 e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f))
Jens Geyer0e87c462013-06-18 22:25:07 +0200439 return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
440 }
Jens Geyer2f971e82014-11-18 21:53:17 +0100441
Jens Geyer0e87c462013-06-18 22:25:07 +0200442 return v, p.ParsePostValue()
443}
444
John Boiles57852792018-01-05 14:37:05 -0800445func (p *TJSONProtocol) Flush(ctx context.Context) (err error) {
Jens Geyerce8d5182013-12-07 00:08:37 +0100446 err = p.writer.Flush()
447 if err == nil {
John Boiles57852792018-01-05 14:37:05 -0800448 err = p.trans.Flush(ctx)
Jens Geyerce8d5182013-12-07 00:08:37 +0100449 }
450 return NewTProtocolException(err)
Jens Geyer0e87c462013-06-18 22:25:07 +0200451}
452
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700453func (p *TJSONProtocol) Skip(ctx context.Context, fieldType TType) (err error) {
454 return SkipDefaultDepth(ctx, p, fieldType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200455}
456
457func (p *TJSONProtocol) Transport() TTransport {
458 return p.trans
459}
460
461func (p *TJSONProtocol) OutputElemListBegin(elemType TType, size int) error {
462 if e := p.OutputListBegin(); e != nil {
463 return e
464 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200465 s, e1 := p.TypeIdToString(elemType)
466 if e1 != nil {
467 return e1
468 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700469 if e := p.OutputString(s); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200470 return e
471 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700472 if e := p.OutputI64(int64(size)); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200473 return e
474 }
475 return nil
476}
477
Jens Geyer0e87c462013-06-18 22:25:07 +0200478func (p *TJSONProtocol) ParseElemListBegin() (elemType TType, size int, e error) {
479 if isNull, e := p.ParseListBegin(); isNull || e != nil {
480 return VOID, 0, e
481 }
Yuxuan 'fishy' Wange79f7642020-06-12 22:22:35 -0700482 // We don't really use the ctx in ReadString implementation,
483 // so this is safe for now.
484 // We might want to add context to ParseElemListBegin if we start to use
485 // ctx in ReadString implementation in the future.
486 sElemType, err := p.ReadString(context.Background())
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200487 if err != nil {
488 return VOID, size, err
489 }
490 elemType, err = p.StringToTypeId(sElemType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200491 if err != nil {
492 return elemType, size, err
493 }
Yuxuan 'fishy' Wang6583f4e2021-03-25 17:00:31 -0700494 nSize, _, err := p.ParseI64()
495 if err != nil {
496 return elemType, 0, err
497 }
Hasnain Lakhani845a87a2025-05-27 22:31:42 -0700498 size = int(nSize)
499
500 minElemSize := p.getMinSerializedSize(elemType)
501 totalMinSize := int32(nSize) * minElemSize
502 err = checkSizeForProtocol(totalMinSize, p.cfg)
Yuxuan 'fishy' Wang6583f4e2021-03-25 17:00:31 -0700503 if err != nil {
504 return elemType, 0, err
505 }
Yuxuan 'fishy' Wang6583f4e2021-03-25 17:00:31 -0700506 return elemType, size, nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200507}
508
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200509func (p *TJSONProtocol) TypeIdToString(fieldType TType) (string, error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200510 switch byte(fieldType) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200511 case BOOL:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200512 return "tf", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200513 case BYTE:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200514 return "i8", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200515 case I16:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200516 return "i16", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200517 case I32:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200518 return "i32", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200519 case I64:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200520 return "i64", nil
521 case DOUBLE:
522 return "dbl", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200523 case STRING:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200524 return "str", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200525 case STRUCT:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200526 return "rec", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200527 case MAP:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200528 return "map", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200529 case SET:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200530 return "set", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200531 case LIST:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200532 return "lst", nil
Yuxuan 'fishy' Wang2acfe0f2022-10-21 10:27:40 -0700533 case UUID:
534 return "uid", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200535 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200536
537 e := fmt.Errorf("Unknown fieldType: %d", int(fieldType))
538 return "", NewTProtocolExceptionWithType(INVALID_DATA, e)
Jens Geyer0e87c462013-06-18 22:25:07 +0200539}
540
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200541func (p *TJSONProtocol) StringToTypeId(fieldType string) (TType, error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200542 switch fieldType {
Jens Geyer0e87c462013-06-18 22:25:07 +0200543 case "tf":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200544 return TType(BOOL), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200545 case "i8":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200546 return TType(BYTE), nil
547 case "i16":
548 return TType(I16), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200549 case "i32":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200550 return TType(I32), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200551 case "i64":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200552 return TType(I64), nil
553 case "dbl":
554 return TType(DOUBLE), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200555 case "str":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200556 return TType(STRING), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200557 case "rec":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200558 return TType(STRUCT), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200559 case "map":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200560 return TType(MAP), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200561 case "set":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200562 return TType(SET), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200563 case "lst":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200564 return TType(LIST), nil
Yuxuan 'fishy' Wang2acfe0f2022-10-21 10:27:40 -0700565 case "uid":
566 return TType(UUID), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200567 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200568
569 e := fmt.Errorf("Unknown type identifier: %s", fieldType)
570 return TType(STOP), NewTProtocolExceptionWithType(INVALID_DATA, e)
Jens Geyer0e87c462013-06-18 22:25:07 +0200571}
Yuxuan 'fishy' Wangc4d1c0d2020-12-16 17:10:48 -0800572
Hasnain Lakhani845a87a2025-05-27 22:31:42 -0700573// Return the minimum number of bytes a type will consume on the wire
574func (p *TJSONProtocol) getMinSerializedSize(ttype TType) int32 {
575 switch ttype {
576 case STOP:
577 return 1 // T_STOP needs to count itself
578 case VOID:
579 return 1 // T_VOID needs to count itself
580 case BOOL:
581 return 1 // written as int
582 case BYTE:
583 return 1
584 case DOUBLE:
585 return 1
586 case I16:
587 return 1
588 case I32:
589 return 1
590 case I64:
591 return 1
592 case STRING:
593 return 2 // empty string
594 case STRUCT:
595 return 2 // empty struct
596 case MAP:
597 return 2 // empty map
598 case SET:
599 return 2 // empty set
600 case LIST:
601 return 2 // empty list
602 case UUID:
603 return 16 // empty UUID
604 default:
605 return 1 // unknown type
606 }
607}
608
Yuxuan 'fishy' Wangc4d1c0d2020-12-16 17:10:48 -0800609var _ TConfigurationSetter = (*TJSONProtocol)(nil)