blob: 957d8ed8374e5aa63a7d99b907b0004b998f17af [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 (
23 "encoding/base64"
24 "fmt"
25)
26
27const (
28 THRIFT_JSON_PROTOCOL_VERSION = 1
29)
30
31// for references to _ParseContext see tsimplejson_protocol.go
32
33// JSON protocol implementation for thrift.
34//
35// This protocol produces/consumes a simple output format
36// suitable for parsing by scripting languages. It should not be
37// confused with the full-featured TJSONProtocol.
38//
39type TJSONProtocol struct {
40 *TSimpleJSONProtocol
41}
42
43// Constructor
44func NewTJSONProtocol(t TTransport) *TJSONProtocol {
45 v := &TJSONProtocol{TSimpleJSONProtocol: NewTSimpleJSONProtocol(t)}
46 v.parseContextStack = append(v.parseContextStack, int(_CONTEXT_IN_TOPLEVEL))
47 v.dumpContext = append(v.dumpContext, int(_CONTEXT_IN_TOPLEVEL))
48 return v
49}
50
51// Factory
52type TJSONProtocolFactory struct{}
53
54func (p *TJSONProtocolFactory) GetProtocol(trans TTransport) TProtocol {
55 return NewTJSONProtocol(trans)
56}
57
58func NewTJSONProtocolFactory() *TJSONProtocolFactory {
59 return &TJSONProtocolFactory{}
60}
61
62func (p *TJSONProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) error {
63 if e := p.OutputListBegin(); e != nil {
64 return e
65 }
66 if e := p.WriteI32(THRIFT_JSON_PROTOCOL_VERSION); e != nil {
67 return e
68 }
69 if e := p.WriteString(name); e != nil {
70 return e
71 }
72 if e := p.WriteByte(byte(typeId)); e != nil {
73 return e
74 }
75 if e := p.WriteI32(seqId); e != nil {
76 return e
77 }
78 return nil
79}
80
81func (p *TJSONProtocol) WriteMessageEnd() error {
82 return p.OutputListEnd()
83}
84
85func (p *TJSONProtocol) WriteStructBegin(name string) error {
86 if e := p.OutputObjectBegin(); e != nil {
87 return e
88 }
89 return nil
90}
91
92func (p *TJSONProtocol) WriteStructEnd() error {
93 return p.OutputObjectEnd()
94}
95
96func (p *TJSONProtocol) WriteFieldBegin(name string, typeId TType, id int16) error {
97 if e := p.WriteI16(id); e != nil {
98 return e
99 }
100 if e := p.OutputObjectBegin(); e != nil {
101 return e
102 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200103 s, e1 := p.TypeIdToString(typeId)
104 if e1 != nil {
105 return e1
106 }
107 if e := p.WriteString(s); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200108 return e
109 }
110 return nil
111}
112
113func (p *TJSONProtocol) WriteFieldEnd() error {
114 return p.OutputObjectEnd()
115}
116
117func (p *TJSONProtocol) WriteFieldStop() error { return nil }
118
119func (p *TJSONProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error {
120 if e := p.OutputListBegin(); e != nil {
121 return e
122 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200123 s, e1 := p.TypeIdToString(keyType)
124 if e1 != nil {
125 return e1
126 }
127 if e := p.WriteString(s); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200128 return e
129 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200130 s, e1 = p.TypeIdToString(valueType)
131 if e1 != nil {
132 return e1
133 }
134 if e := p.WriteString(s); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200135 return e
136 }
137 return p.WriteI64(int64(size))
138}
139
140func (p *TJSONProtocol) WriteMapEnd() error {
141 return p.OutputListEnd()
142}
143
144func (p *TJSONProtocol) WriteListBegin(elemType TType, size int) error {
145 return p.OutputElemListBegin(elemType, size)
146}
147
148func (p *TJSONProtocol) WriteListEnd() error {
149 return p.OutputListEnd()
150}
151
152func (p *TJSONProtocol) WriteSetBegin(elemType TType, size int) error {
153 return p.OutputElemListBegin(elemType, size)
154}
155
156func (p *TJSONProtocol) WriteSetEnd() error {
157 return p.OutputListEnd()
158}
159
160func (p *TJSONProtocol) WriteBool(b bool) error {
161 return p.OutputBool(b)
162}
163
164func (p *TJSONProtocol) WriteByte(b byte) error {
165 return p.WriteI32(int32(b))
166}
167
168func (p *TJSONProtocol) WriteI16(v int16) error {
169 return p.WriteI32(int32(v))
170}
171
172func (p *TJSONProtocol) WriteI32(v int32) error {
173 return p.OutputI64(int64(v))
174}
175
176func (p *TJSONProtocol) WriteI64(v int64) error {
177 return p.OutputI64(int64(v))
178}
179
180func (p *TJSONProtocol) WriteDouble(v float64) error {
181 return p.OutputF64(v)
182}
183
184func (p *TJSONProtocol) WriteString(v string) error {
185 return p.OutputString(v)
186}
187
188func (p *TJSONProtocol) WriteBinary(v []byte) error {
189 // JSON library only takes in a string,
190 // not an arbitrary byte array, to ensure bytes are transmitted
191 // efficiently we must convert this into a valid JSON string
192 // therefore we use base64 encoding to avoid excessive escaping/quoting
193 if e := p.OutputPreValue(); e != nil {
194 return e
195 }
196 p.writer.Write(JSON_QUOTE_BYTES)
197 writer := base64.NewEncoder(base64.StdEncoding, p.writer)
198 if _, e := writer.Write(v); e != nil {
199 return NewTProtocolException(e)
200 }
201 writer.Close()
202 p.writer.Write(JSON_QUOTE_BYTES)
203 return p.OutputPostValue()
204}
205
206// Reading methods.
207
208func (p *TJSONProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) {
209 if isNull, err := p.ParseListBegin(); isNull || err != nil {
210 return name, typeId, seqId, err
211 }
212 version, err := p.ReadI32()
213 if err != nil {
214 return name, typeId, seqId, err
215 }
216 if version != THRIFT_JSON_PROTOCOL_VERSION {
217 e := fmt.Errorf("Unknown Protocol version %d, expected version %d", version, THRIFT_JSON_PROTOCOL_VERSION)
218 return name, typeId, seqId, NewTProtocolExceptionWithType(INVALID_DATA, e)
219
220 }
221 if name, err = p.ReadString(); err != nil {
222 return name, typeId, seqId, err
223 }
224 bTypeId, err := p.ReadByte()
225 typeId = TMessageType(bTypeId)
226 if err != nil {
227 return name, typeId, seqId, err
228 }
229 if seqId, err = p.ReadI32(); err != nil {
230 return name, typeId, seqId, err
231 }
232 return name, typeId, seqId, nil
233}
234
235func (p *TJSONProtocol) ReadMessageEnd() error {
236 err := p.ParseListEnd()
237 return err
238}
239
240func (p *TJSONProtocol) ReadStructBegin() (name string, err error) {
241 _, err = p.ParseObjectStart()
242 return "", err
243}
244
245func (p *TJSONProtocol) ReadStructEnd() error {
246 return p.ParseObjectEnd()
247}
248
249func (p *TJSONProtocol) ReadFieldBegin() (string, TType, int16, error) {
250 if p.reader.Buffered() < 1 {
251 return "", STOP, -1, nil
252 }
253 b, _ := p.reader.Peek(1)
254 if len(b) < 1 || b[0] == JSON_RBRACE[0] || b[0] == JSON_RBRACKET[0] {
255 return "", STOP, -1, nil
256 }
257 fieldId, err := p.ReadI16()
258 if err != nil {
259 return "", STOP, fieldId, err
260 }
261 if _, err = p.ParseObjectStart(); err != nil {
262 return "", STOP, fieldId, err
263 }
264 sType, err := p.ReadString()
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200265 if err != nil {
266 return "", STOP, fieldId, err
267 }
268 fType, err := p.StringToTypeId(sType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200269 return "", fType, fieldId, err
270}
271
272func (p *TJSONProtocol) ReadFieldEnd() error {
273 return p.ParseObjectEnd()
274}
275
276func (p *TJSONProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, e error) {
277 if isNull, e := p.ParseListBegin(); isNull || e != nil {
278 return VOID, VOID, 0, e
279 }
280
281 // read keyType
282 sKeyType, e := p.ReadString()
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200283 if e != nil {
284 return keyType, valueType, size, e
285 }
286 keyType, e = p.StringToTypeId(sKeyType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200287 if e != nil {
288 return keyType, valueType, size, e
289 }
290
291 // read valueType
292 sValueType, e := p.ReadString()
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200293 if e != nil {
294 return keyType, valueType, size, e
295 }
296 valueType, e = p.StringToTypeId(sValueType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200297 if e != nil {
298 return keyType, valueType, size, e
299 }
300
301 // read size
302 iSize, err := p.ReadI64()
303 size = int(iSize)
304 return keyType, valueType, size, err
305}
306
307func (p *TJSONProtocol) ReadMapEnd() error {
308 return p.ParseListEnd()
309}
310
311func (p *TJSONProtocol) ReadListBegin() (elemType TType, size int, e error) {
312 return p.ParseElemListBegin()
313}
314
315func (p *TJSONProtocol) ReadListEnd() error {
316 return p.ParseListEnd()
317}
318
319func (p *TJSONProtocol) ReadSetBegin() (elemType TType, size int, e error) {
320 return p.ParseElemListBegin()
321}
322
323func (p *TJSONProtocol) ReadSetEnd() error {
324 return p.ParseListEnd()
325}
326
327func (p *TJSONProtocol) ReadBool() (bool, error) {
328 var value bool
329 if err := p.ParsePreValue(); err != nil {
330 return value, err
331 }
332 b, _ := p.reader.Peek(len(JSON_FALSE))
333 if len(b) > 0 {
334 switch b[0] {
335 case JSON_TRUE[0]:
336 if string(b[0:len(JSON_TRUE)]) == string(JSON_TRUE) {
337 p.reader.Read(b[0:len(JSON_TRUE)])
338 value = true
339 } else {
340 e := fmt.Errorf("Expected \"true\" but found: %s", string(b))
341 return value, NewTProtocolExceptionWithType(INVALID_DATA, e)
342 }
343 break
344 case JSON_FALSE[0]:
345 if string(b[0:len(JSON_FALSE)]) == string(JSON_FALSE) {
346 p.reader.Read(b[0:len(JSON_FALSE)])
347 value = false
348 } else {
349 e := fmt.Errorf("Expected \"false\" but found: %s", string(b))
350 return value, NewTProtocolExceptionWithType(INVALID_DATA, e)
351 }
352 break
353 case JSON_NULL[0]:
354 if string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
355 p.reader.Read(b[0:len(JSON_NULL)])
356 value = false
357 } else {
358 e := fmt.Errorf("Expected \"null\" but found: %s", string(b))
359 return value, NewTProtocolExceptionWithType(INVALID_DATA, e)
360 }
361 default:
362 e := fmt.Errorf("Expected \"true\", \"false\", or \"null\" but found: %s", string(b))
363 return value, NewTProtocolExceptionWithType(INVALID_DATA, e)
364 }
365 }
366 return value, p.ParsePostValue()
367}
368
369func (p *TJSONProtocol) ReadByte() (byte, error) {
370 v, err := p.ReadI64()
371 return byte(v), err
372}
373
374func (p *TJSONProtocol) ReadI16() (int16, error) {
375 v, err := p.ReadI64()
376 return int16(v), err
377}
378
379func (p *TJSONProtocol) ReadI32() (int32, error) {
380 v, err := p.ReadI64()
381 return int32(v), err
382}
383
384func (p *TJSONProtocol) ReadI64() (int64, error) {
385 v, _, err := p.ParseI64()
386 return v, err
387}
388
389func (p *TJSONProtocol) ReadDouble() (float64, error) {
390 v, _, err := p.ParseF64()
391 return v, err
392}
393
394func (p *TJSONProtocol) ReadString() (string, error) {
395 var v string
396 if err := p.ParsePreValue(); err != nil {
397 return v, err
398 }
399 b, _ := p.reader.Peek(len(JSON_NULL))
400 if len(b) > 0 && b[0] == JSON_QUOTE {
401 p.reader.ReadByte()
402 value, err := p.ParseStringBody()
403 v = value
404 if err != nil {
405 return v, err
406 }
407 } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
408 _, err := p.reader.Read(b[0:len(JSON_NULL)])
409 if err != nil {
410 return v, NewTProtocolException(err)
411 }
412 } else {
413 e := fmt.Errorf("Expected a JSON string, found %s", string(b))
414 return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
415 }
416 return v, p.ParsePostValue()
417}
418
419func (p *TJSONProtocol) ReadBinary() ([]byte, error) {
420 var v []byte
421 if err := p.ParsePreValue(); err != nil {
422 return nil, err
423 }
424 b, _ := p.reader.Peek(len(JSON_NULL))
425 if len(b) > 0 && b[0] == JSON_QUOTE {
426 p.reader.ReadByte()
427 value, err := p.ParseBase64EncodedBody()
428 v = value
429 if err != nil {
430 return v, err
431 }
432 } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
433 _, err := p.reader.Read(b[0:len(JSON_NULL)])
434 if err != nil {
435 return v, NewTProtocolException(err)
436 }
437 } else {
438 e := fmt.Errorf("Expected a JSON string, found %s", string(b))
439 return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
440 }
441 return v, p.ParsePostValue()
442}
443
444func (p *TJSONProtocol) Flush() (err error) {
445 return NewTProtocolException(p.writer.Flush())
446}
447
448func (p *TJSONProtocol) Skip(fieldType TType) (err error) {
449 return SkipDefaultDepth(p, fieldType)
450}
451
452func (p *TJSONProtocol) Transport() TTransport {
453 return p.trans
454}
455
456func (p *TJSONProtocol) OutputElemListBegin(elemType TType, size int) error {
457 if e := p.OutputListBegin(); e != nil {
458 return e
459 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200460 s, e1 := p.TypeIdToString(elemType)
461 if e1 != nil {
462 return e1
463 }
464 if e := p.WriteString(s); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200465 return e
466 }
467 if e := p.WriteI64(int64(size)); e != nil {
468 return e
469 }
470 return nil
471}
472
Jens Geyer0e87c462013-06-18 22:25:07 +0200473func (p *TJSONProtocol) ParseElemListBegin() (elemType TType, size int, e error) {
474 if isNull, e := p.ParseListBegin(); isNull || e != nil {
475 return VOID, 0, e
476 }
477 sElemType, err := p.ReadString()
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200478 if err != nil {
479 return VOID, size, err
480 }
481 elemType, err = p.StringToTypeId(sElemType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200482 if err != nil {
483 return elemType, size, err
484 }
485 nSize, err2 := p.ReadI64()
486 size = int(nSize)
487 return elemType, size, err2
488}
489
490func (p *TJSONProtocol) readElemListBegin() (elemType TType, size int, e error) {
491 if isNull, e := p.ParseListBegin(); isNull || e != nil {
492 return VOID, 0, e
493 }
494 sElemType, err := p.ReadString()
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200495 if err != nil {
496 return VOID, size, err
497 }
498 elemType, err = p.StringToTypeId(sElemType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200499 if err != nil {
500 return elemType, size, err
501 }
502 nSize, err2 := p.ReadI64()
503 size = int(nSize)
504 return elemType, size, err2
505}
506
507func (p *TJSONProtocol) writeElemListBegin(elemType TType, size int) error {
508 if e := p.OutputListBegin(); e != nil {
509 return e
510 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200511 s, e1 := p.TypeIdToString(elemType)
512 if e1 != nil {
513 return e1
514 }
515 if e := p.OutputString(s); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200516 return e
517 }
518 if e := p.OutputI64(int64(size)); e != nil {
519 return e
520 }
521 return nil
522}
523
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200524func (p *TJSONProtocol) TypeIdToString(fieldType TType) (string, error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200525 switch byte(fieldType) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200526 case BOOL:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200527 return "tf", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200528 case BYTE:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200529 return "i8", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200530 case I16:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200531 return "i16", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200532 case I32:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200533 return "i32", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200534 case I64:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200535 return "i64", nil
536 case DOUBLE:
537 return "dbl", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200538 case STRING:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200539 return "str", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200540 case STRUCT:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200541 return "rec", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200542 case MAP:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200543 return "map", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200544 case SET:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200545 return "set", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200546 case LIST:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200547 return "lst", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200548 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200549
550 e := fmt.Errorf("Unknown fieldType: %d", int(fieldType))
551 return "", NewTProtocolExceptionWithType(INVALID_DATA, e)
Jens Geyer0e87c462013-06-18 22:25:07 +0200552}
553
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200554func (p *TJSONProtocol) StringToTypeId(fieldType string) (TType, error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200555 switch fieldType {
Jens Geyer0e87c462013-06-18 22:25:07 +0200556 case "tf":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200557 return TType(BOOL), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200558 case "i8":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200559 return TType(BYTE), nil
560 case "i16":
561 return TType(I16), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200562 case "i32":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200563 return TType(I32), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200564 case "i64":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200565 return TType(I64), nil
566 case "dbl":
567 return TType(DOUBLE), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200568 case "str":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200569 return TType(STRING), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200570 case "rec":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200571 return TType(STRUCT), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200572 case "map":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200573 return TType(MAP), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200574 case "set":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200575 return TType(SET), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200576 case "lst":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200577 return TType(LIST), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200578 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200579
580 e := fmt.Errorf("Unknown type identifier: %s", fieldType)
581 return TType(STOP), NewTProtocolExceptionWithType(INVALID_DATA, e)
Jens Geyer0e87c462013-06-18 22:25:07 +0200582}