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