blob: 7a5e16e6460edfb92ec05650bed71e08f1505318 [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 {
Jens Geyerbf3a19d2013-12-17 21:39:30 +0100161 //return p.OutputBool(b) - not for Thrift JSON
162 if b {
163 return p.WriteI32(1)
164 } else {
165 return p.WriteI32(0)
166 }
Jens Geyer0e87c462013-06-18 22:25:07 +0200167}
168
169func (p *TJSONProtocol) WriteByte(b byte) error {
170 return p.WriteI32(int32(b))
171}
172
173func (p *TJSONProtocol) WriteI16(v int16) error {
174 return p.WriteI32(int32(v))
175}
176
177func (p *TJSONProtocol) WriteI32(v int32) error {
178 return p.OutputI64(int64(v))
179}
180
181func (p *TJSONProtocol) WriteI64(v int64) error {
182 return p.OutputI64(int64(v))
183}
184
185func (p *TJSONProtocol) WriteDouble(v float64) error {
186 return p.OutputF64(v)
187}
188
189func (p *TJSONProtocol) WriteString(v string) error {
190 return p.OutputString(v)
191}
192
193func (p *TJSONProtocol) WriteBinary(v []byte) error {
194 // JSON library only takes in a string,
195 // not an arbitrary byte array, to ensure bytes are transmitted
196 // efficiently we must convert this into a valid JSON string
197 // therefore we use base64 encoding to avoid excessive escaping/quoting
198 if e := p.OutputPreValue(); e != nil {
199 return e
200 }
201 p.writer.Write(JSON_QUOTE_BYTES)
202 writer := base64.NewEncoder(base64.StdEncoding, p.writer)
203 if _, e := writer.Write(v); e != nil {
204 return NewTProtocolException(e)
205 }
206 writer.Close()
207 p.writer.Write(JSON_QUOTE_BYTES)
208 return p.OutputPostValue()
209}
210
211// Reading methods.
212
213func (p *TJSONProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) {
214 if isNull, err := p.ParseListBegin(); isNull || err != nil {
215 return name, typeId, seqId, err
216 }
217 version, err := p.ReadI32()
218 if err != nil {
219 return name, typeId, seqId, err
220 }
221 if version != THRIFT_JSON_PROTOCOL_VERSION {
222 e := fmt.Errorf("Unknown Protocol version %d, expected version %d", version, THRIFT_JSON_PROTOCOL_VERSION)
223 return name, typeId, seqId, NewTProtocolExceptionWithType(INVALID_DATA, e)
224
225 }
226 if name, err = p.ReadString(); err != nil {
227 return name, typeId, seqId, err
228 }
229 bTypeId, err := p.ReadByte()
230 typeId = TMessageType(bTypeId)
231 if err != nil {
232 return name, typeId, seqId, err
233 }
234 if seqId, err = p.ReadI32(); err != nil {
235 return name, typeId, seqId, err
236 }
237 return name, typeId, seqId, nil
238}
239
240func (p *TJSONProtocol) ReadMessageEnd() error {
241 err := p.ParseListEnd()
242 return err
243}
244
245func (p *TJSONProtocol) ReadStructBegin() (name string, err error) {
246 _, err = p.ParseObjectStart()
247 return "", err
248}
249
250func (p *TJSONProtocol) ReadStructEnd() error {
251 return p.ParseObjectEnd()
252}
253
254func (p *TJSONProtocol) ReadFieldBegin() (string, TType, int16, error) {
255 if p.reader.Buffered() < 1 {
256 return "", STOP, -1, nil
257 }
258 b, _ := p.reader.Peek(1)
259 if len(b) < 1 || b[0] == JSON_RBRACE[0] || b[0] == JSON_RBRACKET[0] {
260 return "", STOP, -1, nil
261 }
262 fieldId, err := p.ReadI16()
263 if err != nil {
264 return "", STOP, fieldId, err
265 }
266 if _, err = p.ParseObjectStart(); err != nil {
267 return "", STOP, fieldId, err
268 }
269 sType, err := p.ReadString()
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200270 if err != nil {
271 return "", STOP, fieldId, err
272 }
273 fType, err := p.StringToTypeId(sType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200274 return "", fType, fieldId, err
275}
276
277func (p *TJSONProtocol) ReadFieldEnd() error {
278 return p.ParseObjectEnd()
279}
280
281func (p *TJSONProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, e error) {
282 if isNull, e := p.ParseListBegin(); isNull || e != nil {
283 return VOID, VOID, 0, e
284 }
285
286 // read keyType
287 sKeyType, e := p.ReadString()
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200288 if e != nil {
289 return keyType, valueType, size, e
290 }
291 keyType, e = p.StringToTypeId(sKeyType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200292 if e != nil {
293 return keyType, valueType, size, e
294 }
295
296 // read valueType
297 sValueType, e := p.ReadString()
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200298 if e != nil {
299 return keyType, valueType, size, e
300 }
301 valueType, e = p.StringToTypeId(sValueType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200302 if e != nil {
303 return keyType, valueType, size, e
304 }
305
306 // read size
307 iSize, err := p.ReadI64()
308 size = int(iSize)
309 return keyType, valueType, size, err
310}
311
312func (p *TJSONProtocol) ReadMapEnd() error {
313 return p.ParseListEnd()
314}
315
316func (p *TJSONProtocol) ReadListBegin() (elemType TType, size int, e error) {
317 return p.ParseElemListBegin()
318}
319
320func (p *TJSONProtocol) ReadListEnd() error {
321 return p.ParseListEnd()
322}
323
324func (p *TJSONProtocol) ReadSetBegin() (elemType TType, size int, e error) {
325 return p.ParseElemListBegin()
326}
327
328func (p *TJSONProtocol) ReadSetEnd() error {
329 return p.ParseListEnd()
330}
331
332func (p *TJSONProtocol) ReadBool() (bool, error) {
Jens Geyerbf3a19d2013-12-17 21:39:30 +0100333 value, err := p.ReadI32();
334 return (value != 0), err
Jens Geyer0e87c462013-06-18 22:25:07 +0200335}
336
337func (p *TJSONProtocol) ReadByte() (byte, error) {
338 v, err := p.ReadI64()
339 return byte(v), err
340}
341
342func (p *TJSONProtocol) ReadI16() (int16, error) {
343 v, err := p.ReadI64()
344 return int16(v), err
345}
346
347func (p *TJSONProtocol) ReadI32() (int32, error) {
348 v, err := p.ReadI64()
349 return int32(v), err
350}
351
352func (p *TJSONProtocol) ReadI64() (int64, error) {
353 v, _, err := p.ParseI64()
354 return v, err
355}
356
357func (p *TJSONProtocol) ReadDouble() (float64, error) {
358 v, _, err := p.ParseF64()
359 return v, err
360}
361
362func (p *TJSONProtocol) ReadString() (string, error) {
363 var v string
364 if err := p.ParsePreValue(); err != nil {
365 return v, err
366 }
367 b, _ := p.reader.Peek(len(JSON_NULL))
368 if len(b) > 0 && b[0] == JSON_QUOTE {
369 p.reader.ReadByte()
370 value, err := p.ParseStringBody()
371 v = value
372 if err != nil {
373 return v, err
374 }
375 } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
376 _, err := p.reader.Read(b[0:len(JSON_NULL)])
377 if err != nil {
378 return v, NewTProtocolException(err)
379 }
380 } else {
381 e := fmt.Errorf("Expected a JSON string, found %s", string(b))
382 return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
383 }
384 return v, p.ParsePostValue()
385}
386
387func (p *TJSONProtocol) ReadBinary() ([]byte, error) {
388 var v []byte
389 if err := p.ParsePreValue(); err != nil {
390 return nil, err
391 }
392 b, _ := p.reader.Peek(len(JSON_NULL))
393 if len(b) > 0 && b[0] == JSON_QUOTE {
394 p.reader.ReadByte()
395 value, err := p.ParseBase64EncodedBody()
396 v = value
397 if err != nil {
398 return v, err
399 }
400 } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
401 _, err := p.reader.Read(b[0:len(JSON_NULL)])
402 if err != nil {
403 return v, NewTProtocolException(err)
404 }
405 } else {
406 e := fmt.Errorf("Expected a JSON string, found %s", string(b))
407 return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
408 }
409 return v, p.ParsePostValue()
410}
411
412func (p *TJSONProtocol) Flush() (err error) {
Jens Geyerce8d5182013-12-07 00:08:37 +0100413 err = p.writer.Flush()
414 if err == nil {
415 err = p.trans.Flush()
416 }
417 return NewTProtocolException(err)
Jens Geyer0e87c462013-06-18 22:25:07 +0200418}
419
420func (p *TJSONProtocol) Skip(fieldType TType) (err error) {
421 return SkipDefaultDepth(p, fieldType)
422}
423
424func (p *TJSONProtocol) Transport() TTransport {
425 return p.trans
426}
427
428func (p *TJSONProtocol) OutputElemListBegin(elemType TType, size int) error {
429 if e := p.OutputListBegin(); e != nil {
430 return e
431 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200432 s, e1 := p.TypeIdToString(elemType)
433 if e1 != nil {
434 return e1
435 }
436 if e := p.WriteString(s); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200437 return e
438 }
439 if e := p.WriteI64(int64(size)); e != nil {
440 return e
441 }
442 return nil
443}
444
Jens Geyer0e87c462013-06-18 22:25:07 +0200445func (p *TJSONProtocol) ParseElemListBegin() (elemType TType, size int, e error) {
446 if isNull, e := p.ParseListBegin(); isNull || e != nil {
447 return VOID, 0, e
448 }
449 sElemType, err := p.ReadString()
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200450 if err != nil {
451 return VOID, size, err
452 }
453 elemType, err = p.StringToTypeId(sElemType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200454 if err != nil {
455 return elemType, size, err
456 }
457 nSize, err2 := p.ReadI64()
458 size = int(nSize)
459 return elemType, size, err2
460}
461
462func (p *TJSONProtocol) readElemListBegin() (elemType TType, size int, e error) {
463 if isNull, e := p.ParseListBegin(); isNull || e != nil {
464 return VOID, 0, e
465 }
466 sElemType, err := p.ReadString()
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200467 if err != nil {
468 return VOID, size, err
469 }
470 elemType, err = p.StringToTypeId(sElemType)
Jens Geyer0e87c462013-06-18 22:25:07 +0200471 if err != nil {
472 return elemType, size, err
473 }
474 nSize, err2 := p.ReadI64()
475 size = int(nSize)
476 return elemType, size, err2
477}
478
479func (p *TJSONProtocol) writeElemListBegin(elemType TType, size int) error {
480 if e := p.OutputListBegin(); e != nil {
481 return e
482 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200483 s, e1 := p.TypeIdToString(elemType)
484 if e1 != nil {
485 return e1
486 }
487 if e := p.OutputString(s); e != nil {
Jens Geyer0e87c462013-06-18 22:25:07 +0200488 return e
489 }
490 if e := p.OutputI64(int64(size)); e != nil {
491 return e
492 }
493 return nil
494}
495
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200496func (p *TJSONProtocol) TypeIdToString(fieldType TType) (string, error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200497 switch byte(fieldType) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200498 case BOOL:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200499 return "tf", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200500 case BYTE:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200501 return "i8", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200502 case I16:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200503 return "i16", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200504 case I32:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200505 return "i32", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200506 case I64:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200507 return "i64", nil
508 case DOUBLE:
509 return "dbl", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200510 case STRING:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200511 return "str", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200512 case STRUCT:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200513 return "rec", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200514 case MAP:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200515 return "map", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200516 case SET:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200517 return "set", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200518 case LIST:
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200519 return "lst", nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200520 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200521
522 e := fmt.Errorf("Unknown fieldType: %d", int(fieldType))
523 return "", NewTProtocolExceptionWithType(INVALID_DATA, e)
Jens Geyer0e87c462013-06-18 22:25:07 +0200524}
525
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200526func (p *TJSONProtocol) StringToTypeId(fieldType string) (TType, error) {
Jens Geyer0e87c462013-06-18 22:25:07 +0200527 switch fieldType {
Jens Geyer0e87c462013-06-18 22:25:07 +0200528 case "tf":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200529 return TType(BOOL), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200530 case "i8":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200531 return TType(BYTE), nil
532 case "i16":
533 return TType(I16), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200534 case "i32":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200535 return TType(I32), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200536 case "i64":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200537 return TType(I64), nil
538 case "dbl":
539 return TType(DOUBLE), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200540 case "str":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200541 return TType(STRING), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200542 case "rec":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200543 return TType(STRUCT), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200544 case "map":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200545 return TType(MAP), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200546 case "set":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200547 return TType(SET), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200548 case "lst":
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200549 return TType(LIST), nil
Jens Geyer0e87c462013-06-18 22:25:07 +0200550 }
Jens Geyer8a0f8d12013-09-10 21:30:41 +0200551
552 e := fmt.Errorf("Unknown type identifier: %s", fieldType)
553 return TType(STOP), NewTProtocolExceptionWithType(INVALID_DATA, e)
Jens Geyer0e87c462013-06-18 22:25:07 +0200554}