1/*
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 (
23	"context"
24	"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.
35//
36// This protocol produces/consumes a simple output format
37// suitable for parsing by scripting languages.  It should not be
38// confused with the full-featured TJSONProtocol.
39//
40type TJSONProtocol struct {
41	*TSimpleJSONProtocol
42}
43
44// Constructor
45func NewTJSONProtocol(t TTransport) *TJSONProtocol {
46	v := &TJSONProtocol{TSimpleJSONProtocol: NewTSimpleJSONProtocol(t)}
47	v.parseContextStack = append(v.parseContextStack, int(_CONTEXT_IN_TOPLEVEL))
48	v.dumpContext = append(v.dumpContext, int(_CONTEXT_IN_TOPLEVEL))
49	return v
50}
51
52// Factory
53type TJSONProtocolFactory struct{}
54
55func (p *TJSONProtocolFactory) GetProtocol(trans TTransport) TProtocol {
56	return NewTJSONProtocol(trans)
57}
58
59func NewTJSONProtocolFactory() *TJSONProtocolFactory {
60	return &TJSONProtocolFactory{}
61}
62
63func (p *TJSONProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) error {
64	p.resetContextStack() // THRIFT-3735
65	if e := p.OutputListBegin(); e != nil {
66		return e
67	}
68	if e := p.WriteI32(THRIFT_JSON_PROTOCOL_VERSION); e != nil {
69		return e
70	}
71	if e := p.WriteString(name); e != nil {
72		return e
73	}
74	if e := p.WriteByte(int8(typeId)); e != nil {
75		return e
76	}
77	if e := p.WriteI32(seqId); e != nil {
78		return e
79	}
80	return nil
81}
82
83func (p *TJSONProtocol) WriteMessageEnd() error {
84	return p.OutputListEnd()
85}
86
87func (p *TJSONProtocol) WriteStructBegin(name string) error {
88	if e := p.OutputObjectBegin(); e != nil {
89		return e
90	}
91	return nil
92}
93
94func (p *TJSONProtocol) WriteStructEnd() error {
95	return p.OutputObjectEnd()
96}
97
98func (p *TJSONProtocol) WriteFieldBegin(name string, typeId TType, id int16) error {
99	if e := p.WriteI16(id); e != nil {
100		return e
101	}
102	if e := p.OutputObjectBegin(); e != nil {
103		return e
104	}
105	s, e1 := p.TypeIdToString(typeId)
106	if e1 != nil {
107		return e1
108	}
109	if e := p.WriteString(s); e != nil {
110		return e
111	}
112	return nil
113}
114
115func (p *TJSONProtocol) WriteFieldEnd() error {
116	return p.OutputObjectEnd()
117}
118
119func (p *TJSONProtocol) WriteFieldStop() error { return nil }
120
121func (p *TJSONProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error {
122	if e := p.OutputListBegin(); e != nil {
123		return e
124	}
125	s, e1 := p.TypeIdToString(keyType)
126	if e1 != nil {
127		return e1
128	}
129	if e := p.WriteString(s); e != nil {
130		return e
131	}
132	s, e1 = p.TypeIdToString(valueType)
133	if e1 != nil {
134		return e1
135	}
136	if e := p.WriteString(s); e != nil {
137		return e
138	}
139	if e := p.WriteI64(int64(size)); e != nil {
140		return e
141	}
142	return p.OutputObjectBegin()
143}
144
145func (p *TJSONProtocol) WriteMapEnd() error {
146	if e := p.OutputObjectEnd(); e != nil {
147		return e
148	}
149	return p.OutputListEnd()
150}
151
152func (p *TJSONProtocol) WriteListBegin(elemType TType, size int) error {
153	return p.OutputElemListBegin(elemType, size)
154}
155
156func (p *TJSONProtocol) WriteListEnd() error {
157	return p.OutputListEnd()
158}
159
160func (p *TJSONProtocol) WriteSetBegin(elemType TType, size int) error {
161	return p.OutputElemListBegin(elemType, size)
162}
163
164func (p *TJSONProtocol) WriteSetEnd() error {
165	return p.OutputListEnd()
166}
167
168func (p *TJSONProtocol) WriteBool(b bool) error {
169	if b {
170		return p.WriteI32(1)
171	}
172	return p.WriteI32(0)
173}
174
175func (p *TJSONProtocol) WriteByte(b int8) error {
176	return p.WriteI32(int32(b))
177}
178
179func (p *TJSONProtocol) WriteI16(v int16) error {
180	return p.WriteI32(int32(v))
181}
182
183func (p *TJSONProtocol) WriteI32(v int32) error {
184	return p.OutputI64(int64(v))
185}
186
187func (p *TJSONProtocol) WriteI64(v int64) error {
188	return p.OutputI64(int64(v))
189}
190
191func (p *TJSONProtocol) WriteDouble(v float64) error {
192	return p.OutputF64(v)
193}
194
195func (p *TJSONProtocol) WriteString(v string) error {
196	return p.OutputString(v)
197}
198
199func (p *TJSONProtocol) WriteBinary(v []byte) error {
200	// JSON library only takes in a string,
201	// not an arbitrary byte array, to ensure bytes are transmitted
202	// efficiently we must convert this into a valid JSON string
203	// therefore we use base64 encoding to avoid excessive escaping/quoting
204	if e := p.OutputPreValue(); e != nil {
205		return e
206	}
207	if _, e := p.write(JSON_QUOTE_BYTES); e != nil {
208		return NewTProtocolException(e)
209	}
210	writer := base64.NewEncoder(base64.StdEncoding, p.writer)
211	if _, e := writer.Write(v); e != nil {
212		p.writer.Reset(p.trans) // THRIFT-3735
213		return NewTProtocolException(e)
214	}
215	if e := writer.Close(); e != nil {
216		return NewTProtocolException(e)
217	}
218	if _, e := p.write(JSON_QUOTE_BYTES); e != nil {
219		return NewTProtocolException(e)
220	}
221	return p.OutputPostValue()
222}
223
224// Reading methods.
225func (p *TJSONProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) {
226	p.resetContextStack() // THRIFT-3735
227	if isNull, err := p.ParseListBegin(); isNull || err != nil {
228		return name, typeId, seqId, err
229	}
230	version, err := p.ReadI32()
231	if err != nil {
232		return name, typeId, seqId, err
233	}
234	if version != THRIFT_JSON_PROTOCOL_VERSION {
235		e := fmt.Errorf("Unknown Protocol version %d, expected version %d", version, THRIFT_JSON_PROTOCOL_VERSION)
236		return name, typeId, seqId, NewTProtocolExceptionWithType(INVALID_DATA, e)
237
238	}
239	if name, err = p.ReadString(); err != nil {
240		return name, typeId, seqId, err
241	}
242	bTypeId, err := p.ReadByte()
243	typeId = TMessageType(bTypeId)
244	if err != nil {
245		return name, typeId, seqId, err
246	}
247	if seqId, err = p.ReadI32(); err != nil {
248		return name, typeId, seqId, err
249	}
250	return name, typeId, seqId, nil
251}
252
253func (p *TJSONProtocol) ReadMessageEnd() error {
254	err := p.ParseListEnd()
255	return err
256}
257
258func (p *TJSONProtocol) ReadStructBegin() (name string, err error) {
259	_, err = p.ParseObjectStart()
260	return "", err
261}
262
263func (p *TJSONProtocol) ReadStructEnd() error {
264	return p.ParseObjectEnd()
265}
266
267func (p *TJSONProtocol) ReadFieldBegin() (string, TType, int16, error) {
268	b, _ := p.reader.Peek(1)
269	if len(b) < 1 || b[0] == JSON_RBRACE[0] || b[0] == JSON_RBRACKET[0] {
270		return "", STOP, -1, nil
271	}
272	fieldId, err := p.ReadI16()
273	if err != nil {
274		return "", STOP, fieldId, err
275	}
276	if _, err = p.ParseObjectStart(); err != nil {
277		return "", STOP, fieldId, err
278	}
279	sType, err := p.ReadString()
280	if err != nil {
281		return "", STOP, fieldId, err
282	}
283	fType, err := p.StringToTypeId(sType)
284	return "", fType, fieldId, err
285}
286
287func (p *TJSONProtocol) ReadFieldEnd() error {
288	return p.ParseObjectEnd()
289}
290
291func (p *TJSONProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, e error) {
292	if isNull, e := p.ParseListBegin(); isNull || e != nil {
293		return VOID, VOID, 0, e
294	}
295
296	// read keyType
297	sKeyType, e := p.ReadString()
298	if e != nil {
299		return keyType, valueType, size, e
300	}
301	keyType, e = p.StringToTypeId(sKeyType)
302	if e != nil {
303		return keyType, valueType, size, e
304	}
305
306	// read valueType
307	sValueType, e := p.ReadString()
308	if e != nil {
309		return keyType, valueType, size, e
310	}
311	valueType, e = p.StringToTypeId(sValueType)
312	if e != nil {
313		return keyType, valueType, size, e
314	}
315
316	// read size
317	iSize, e := p.ReadI64()
318	if e != nil {
319		return keyType, valueType, size, e
320	}
321	size = int(iSize)
322
323	_, e = p.ParseObjectStart()
324	return keyType, valueType, size, e
325}
326
327func (p *TJSONProtocol) ReadMapEnd() error {
328	e := p.ParseObjectEnd()
329	if e != nil {
330		return e
331	}
332	return p.ParseListEnd()
333}
334
335func (p *TJSONProtocol) ReadListBegin() (elemType TType, size int, e error) {
336	return p.ParseElemListBegin()
337}
338
339func (p *TJSONProtocol) ReadListEnd() error {
340	return p.ParseListEnd()
341}
342
343func (p *TJSONProtocol) ReadSetBegin() (elemType TType, size int, e error) {
344	return p.ParseElemListBegin()
345}
346
347func (p *TJSONProtocol) ReadSetEnd() error {
348	return p.ParseListEnd()
349}
350
351func (p *TJSONProtocol) ReadBool() (bool, error) {
352	value, err := p.ReadI32()
353	return (value != 0), err
354}
355
356func (p *TJSONProtocol) ReadByte() (int8, error) {
357	v, err := p.ReadI64()
358	return int8(v), err
359}
360
361func (p *TJSONProtocol) ReadI16() (int16, error) {
362	v, err := p.ReadI64()
363	return int16(v), err
364}
365
366func (p *TJSONProtocol) ReadI32() (int32, error) {
367	v, err := p.ReadI64()
368	return int32(v), err
369}
370
371func (p *TJSONProtocol) ReadI64() (int64, error) {
372	v, _, err := p.ParseI64()
373	return v, err
374}
375
376func (p *TJSONProtocol) ReadDouble() (float64, error) {
377	v, _, err := p.ParseF64()
378	return v, err
379}
380
381func (p *TJSONProtocol) ReadString() (string, error) {
382	var v string
383	if err := p.ParsePreValue(); err != nil {
384		return v, err
385	}
386	f, _ := p.reader.Peek(1)
387	if len(f) > 0 && f[0] == JSON_QUOTE {
388		p.reader.ReadByte()
389		value, err := p.ParseStringBody()
390		v = value
391		if err != nil {
392			return v, err
393		}
394	} else if len(f) > 0 && f[0] == JSON_NULL[0] {
395		b := make([]byte, len(JSON_NULL))
396		_, err := p.reader.Read(b)
397		if err != nil {
398			return v, NewTProtocolException(err)
399		}
400		if string(b) != string(JSON_NULL) {
401			e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b))
402			return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
403		}
404	} else {
405		e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f))
406		return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
407	}
408	return v, p.ParsePostValue()
409}
410
411func (p *TJSONProtocol) ReadBinary() ([]byte, error) {
412	var v []byte
413	if err := p.ParsePreValue(); err != nil {
414		return nil, err
415	}
416	f, _ := p.reader.Peek(1)
417	if len(f) > 0 && f[0] == JSON_QUOTE {
418		p.reader.ReadByte()
419		value, err := p.ParseBase64EncodedBody()
420		v = value
421		if err != nil {
422			return v, err
423		}
424	} else if len(f) > 0 && f[0] == JSON_NULL[0] {
425		b := make([]byte, len(JSON_NULL))
426		_, err := p.reader.Read(b)
427		if err != nil {
428			return v, NewTProtocolException(err)
429		}
430		if string(b) != string(JSON_NULL) {
431			e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b))
432			return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
433		}
434	} else {
435		e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f))
436		return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
437	}
438
439	return v, p.ParsePostValue()
440}
441
442func (p *TJSONProtocol) Flush(ctx context.Context) (err error) {
443	err = p.writer.Flush()
444	if err == nil {
445		err = p.trans.Flush(ctx)
446	}
447	return NewTProtocolException(err)
448}
449
450func (p *TJSONProtocol) Skip(fieldType TType) (err error) {
451	return SkipDefaultDepth(p, fieldType)
452}
453
454func (p *TJSONProtocol) Transport() TTransport {
455	return p.trans
456}
457
458func (p *TJSONProtocol) OutputElemListBegin(elemType TType, size int) error {
459	if e := p.OutputListBegin(); e != nil {
460		return e
461	}
462	s, e1 := p.TypeIdToString(elemType)
463	if e1 != nil {
464		return e1
465	}
466	if e := p.WriteString(s); e != nil {
467		return e
468	}
469	if e := p.WriteI64(int64(size)); e != nil {
470		return e
471	}
472	return nil
473}
474
475func (p *TJSONProtocol) ParseElemListBegin() (elemType TType, size int, e error) {
476	if isNull, e := p.ParseListBegin(); isNull || e != nil {
477		return VOID, 0, e
478	}
479	sElemType, err := p.ReadString()
480	if err != nil {
481		return VOID, size, err
482	}
483	elemType, err = p.StringToTypeId(sElemType)
484	if err != nil {
485		return elemType, size, err
486	}
487	nSize, err2 := p.ReadI64()
488	size = int(nSize)
489	return elemType, size, err2
490}
491
492func (p *TJSONProtocol) readElemListBegin() (elemType TType, size int, e error) {
493	if isNull, e := p.ParseListBegin(); isNull || e != nil {
494		return VOID, 0, e
495	}
496	sElemType, err := p.ReadString()
497	if err != nil {
498		return VOID, size, err
499	}
500	elemType, err = p.StringToTypeId(sElemType)
501	if err != nil {
502		return elemType, size, err
503	}
504	nSize, err2 := p.ReadI64()
505	size = int(nSize)
506	return elemType, size, err2
507}
508
509func (p *TJSONProtocol) writeElemListBegin(elemType TType, size int) error {
510	if e := p.OutputListBegin(); e != nil {
511		return e
512	}
513	s, e1 := p.TypeIdToString(elemType)
514	if e1 != nil {
515		return e1
516	}
517	if e := p.OutputString(s); e != nil {
518		return e
519	}
520	if e := p.OutputI64(int64(size)); e != nil {
521		return e
522	}
523	return nil
524}
525
526func (p *TJSONProtocol) TypeIdToString(fieldType TType) (string, error) {
527	switch byte(fieldType) {
528	case BOOL:
529		return "tf", nil
530	case BYTE:
531		return "i8", nil
532	case I16:
533		return "i16", nil
534	case I32:
535		return "i32", nil
536	case I64:
537		return "i64", nil
538	case DOUBLE:
539		return "dbl", nil
540	case STRING:
541		return "str", nil
542	case STRUCT:
543		return "rec", nil
544	case MAP:
545		return "map", nil
546	case SET:
547		return "set", nil
548	case LIST:
549		return "lst", nil
550	}
551
552	e := fmt.Errorf("Unknown fieldType: %d", int(fieldType))
553	return "", NewTProtocolExceptionWithType(INVALID_DATA, e)
554}
555
556func (p *TJSONProtocol) StringToTypeId(fieldType string) (TType, error) {
557	switch fieldType {
558	case "tf":
559		return TType(BOOL), nil
560	case "i8":
561		return TType(BYTE), nil
562	case "i16":
563		return TType(I16), nil
564	case "i32":
565		return TType(I32), nil
566	case "i64":
567		return TType(I64), nil
568	case "dbl":
569		return TType(DOUBLE), nil
570	case "str":
571		return TType(STRING), nil
572	case "rec":
573		return TType(STRUCT), nil
574	case "map":
575		return TType(MAP), nil
576	case "set":
577		return TType(SET), nil
578	case "lst":
579		return TType(LIST), nil
580	}
581
582	e := fmt.Errorf("Unknown type identifier: %s", fieldType)
583	return TType(STOP), NewTProtocolExceptionWithType(INVALID_DATA, e)
584}
585