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