]>
git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/thrift/lib/py/src/protocol/TProtocol.py
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
10 # http://www.apache.org/licenses/LICENSE-2.0
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
20 from thrift
.Thrift
import TException
, TType
, TFrozenDict
21 from thrift
.transport
.TTransport
import TTransportException
22 from ..compat
import binary_to_str
, str_to_binary
26 from itertools
import islice
27 from six
.moves
import zip
30 class TProtocolException(TException
):
31 """Custom Protocol Exception class"""
42 def __init__(self
, type=UNKNOWN
, message
=None):
43 TException
.__init
__(self
, message
)
47 class TProtocolBase(object):
48 """Base class for Thrift protocol driver."""
50 def __init__(self
, trans
):
52 self
._fast
_decode
= None
53 self
._fast
_encode
= None
56 def _check_length(limit
, length
):
58 raise TTransportException(TTransportException
.NEGATIVE_SIZE
,
59 'Negative length: %d' % length
)
60 if limit
is not None and length
> limit
:
61 raise TTransportException(TTransportException
.SIZE_LIMIT
,
62 'Length exceeded max allowed: %d' % limit
)
64 def writeMessageBegin(self
, name
, ttype
, seqid
):
67 def writeMessageEnd(self
):
70 def writeStructBegin(self
, name
):
73 def writeStructEnd(self
):
76 def writeFieldBegin(self
, name
, ttype
, fid
):
79 def writeFieldEnd(self
):
82 def writeFieldStop(self
):
85 def writeMapBegin(self
, ktype
, vtype
, size
):
88 def writeMapEnd(self
):
91 def writeListBegin(self
, etype
, size
):
94 def writeListEnd(self
):
97 def writeSetBegin(self
, etype
, size
):
100 def writeSetEnd(self
):
103 def writeBool(self
, bool_val
):
106 def writeByte(self
, byte
):
109 def writeI16(self
, i16
):
112 def writeI32(self
, i32
):
115 def writeI64(self
, i64
):
118 def writeDouble(self
, dub
):
121 def writeString(self
, str_val
):
122 self
.writeBinary(str_to_binary(str_val
))
124 def writeBinary(self
, str_val
):
127 def writeUtf8(self
, str_val
):
128 self
.writeString(str_val
.encode('utf8'))
130 def readMessageBegin(self
):
133 def readMessageEnd(self
):
136 def readStructBegin(self
):
139 def readStructEnd(self
):
142 def readFieldBegin(self
):
145 def readFieldEnd(self
):
148 def readMapBegin(self
):
151 def readMapEnd(self
):
154 def readListBegin(self
):
157 def readListEnd(self
):
160 def readSetBegin(self
):
163 def readSetEnd(self
):
181 def readDouble(self
):
184 def readString(self
):
185 return binary_to_str(self
.readBinary())
187 def readBinary(self
):
191 return self
.readString().decode('utf8')
193 def skip(self
, ttype
):
194 if ttype
== TType
.BOOL
:
196 elif ttype
== TType
.BYTE
:
198 elif ttype
== TType
.I16
:
200 elif ttype
== TType
.I32
:
202 elif ttype
== TType
.I64
:
204 elif ttype
== TType
.DOUBLE
:
206 elif ttype
== TType
.STRING
:
208 elif ttype
== TType
.STRUCT
:
209 name
= self
.readStructBegin()
211 (name
, ttype
, id) = self
.readFieldBegin()
212 if ttype
== TType
.STOP
:
217 elif ttype
== TType
.MAP
:
218 (ktype
, vtype
, size
) = self
.readMapBegin()
219 for i
in range(size
):
223 elif ttype
== TType
.SET
:
224 (etype
, size
) = self
.readSetBegin()
225 for i
in range(size
):
228 elif ttype
== TType
.LIST
:
229 (etype
, size
) = self
.readListBegin()
230 for i
in range(size
):
234 raise TProtocolException(
235 TProtocolException
.INVALID_DATA
,
238 # tuple of: ( 'reader method' name, is_container bool, 'writer_method' name )
240 (None, None, False), # 0 TType.STOP
241 (None, None, False), # 1 TType.VOID # TODO: handle void?
242 ('readBool', 'writeBool', False), # 2 TType.BOOL
243 ('readByte', 'writeByte', False), # 3 TType.BYTE and I08
244 ('readDouble', 'writeDouble', False), # 4 TType.DOUBLE
245 (None, None, False), # 5 undefined
246 ('readI16', 'writeI16', False), # 6 TType.I16
247 (None, None, False), # 7 undefined
248 ('readI32', 'writeI32', False), # 8 TType.I32
249 (None, None, False), # 9 undefined
250 ('readI64', 'writeI64', False), # 10 TType.I64
251 ('readString', 'writeString', False), # 11 TType.STRING and UTF7
252 ('readContainerStruct', 'writeContainerStruct', True), # 12 *.STRUCT
253 ('readContainerMap', 'writeContainerMap', True), # 13 TType.MAP
254 ('readContainerSet', 'writeContainerSet', True), # 14 TType.SET
255 ('readContainerList', 'writeContainerList', True), # 15 TType.LIST
256 (None, None, False), # 16 TType.UTF8 # TODO: handle utf8 types?
257 (None, None, False) # 17 TType.UTF16 # TODO: handle utf16 types?
260 def _ttype_handlers(self
, ttype
, spec
):
262 if ttype
!= TType
.STRING
:
263 raise TProtocolException(type=TProtocolException
.INVALID_DATA
,
264 message
='Invalid binary field type %d' % ttype
)
265 return ('readBinary', 'writeBinary', False)
266 if sys
.version_info
[0] == 2 and spec
== 'UTF8':
267 if ttype
!= TType
.STRING
:
268 raise TProtocolException(type=TProtocolException
.INVALID_DATA
,
269 message
='Invalid string field type %d' % ttype
)
270 return ('readUtf8', 'writeUtf8', False)
271 return self
._TTYPE
_HANDLERS
[ttype
] if ttype
< len(self
._TTYPE
_HANDLERS
) else (None, None, False)
273 def _read_by_ttype(self
, ttype
, spec
, espec
):
274 reader_name
, _
, is_container
= self
._ttype
_handlers
(ttype
, espec
)
275 if reader_name
is None:
276 raise TProtocolException(type=TProtocolException
.INVALID_DATA
,
277 message
='Invalid type %d' % (ttype
))
278 reader_func
= getattr(self
, reader_name
)
279 read
= (lambda: reader_func(espec
)) if is_container
else reader_func
283 def readFieldByTType(self
, ttype
, spec
):
284 return next(self
._read
_by
_ttype
(ttype
, spec
, spec
))
286 def readContainerList(self
, spec
):
287 ttype
, tspec
, is_immutable
= spec
288 (list_type
, list_len
) = self
.readListBegin()
289 # TODO: compare types we just decoded with thrift_spec
290 elems
= islice(self
._read
_by
_ttype
(ttype
, spec
, tspec
), list_len
)
291 results
= (tuple if is_immutable
else list)(elems
)
295 def readContainerSet(self
, spec
):
296 ttype
, tspec
, is_immutable
= spec
297 (set_type
, set_len
) = self
.readSetBegin()
298 # TODO: compare types we just decoded with thrift_spec
299 elems
= islice(self
._read
_by
_ttype
(ttype
, spec
, tspec
), set_len
)
300 results
= (frozenset if is_immutable
else set)(elems
)
304 def readContainerStruct(self
, spec
):
305 (obj_class
, obj_spec
) = spec
310 def readContainerMap(self
, spec
):
311 ktype
, kspec
, vtype
, vspec
, is_immutable
= spec
312 (map_ktype
, map_vtype
, map_len
) = self
.readMapBegin()
313 # TODO: compare types we just decoded with thrift_spec and
314 # abort/skip if types disagree
315 keys
= self
._read
_by
_ttype
(ktype
, spec
, kspec
)
316 vals
= self
._read
_by
_ttype
(vtype
, spec
, vspec
)
317 keyvals
= islice(zip(keys
, vals
), map_len
)
318 results
= (TFrozenDict
if is_immutable
else dict)(keyvals
)
322 def readStruct(self
, obj
, thrift_spec
, is_immutable
=False):
325 self
.readStructBegin()
327 (fname
, ftype
, fid
) = self
.readFieldBegin()
328 if ftype
== TType
.STOP
:
331 field
= thrift_spec
[fid
]
335 if field
is not None and ftype
== field
[1]:
338 val
= self
.readFieldByTType(ftype
, fspec
)
342 setattr(obj
, fname
, val
)
350 def writeContainerStruct(self
, val
, spec
):
353 def writeContainerList(self
, val
, spec
):
354 ttype
, tspec
, _
= spec
355 self
.writeListBegin(ttype
, len(val
))
356 for _
in self
._write
_by
_ttype
(ttype
, val
, spec
, tspec
):
360 def writeContainerSet(self
, val
, spec
):
361 ttype
, tspec
, _
= spec
362 self
.writeSetBegin(ttype
, len(val
))
363 for _
in self
._write
_by
_ttype
(ttype
, val
, spec
, tspec
):
367 def writeContainerMap(self
, val
, spec
):
368 ktype
, kspec
, vtype
, vspec
, _
= spec
369 self
.writeMapBegin(ktype
, vtype
, len(val
))
370 for _
in zip(self
._write
_by
_ttype
(ktype
, six
.iterkeys(val
), spec
, kspec
),
371 self
._write
_by
_ttype
(vtype
, six
.itervalues(val
), spec
, vspec
)):
375 def writeStruct(self
, obj
, thrift_spec
):
376 self
.writeStructBegin(obj
.__class
__.__name
__)
377 for field
in thrift_spec
:
381 val
= getattr(obj
, fname
)
383 # skip writing out unset fields
388 self
.writeFieldBegin(fname
, ftype
, fid
)
389 self
.writeFieldByTType(ftype
, val
, fspec
)
391 self
.writeFieldStop()
392 self
.writeStructEnd()
394 def _write_by_ttype(self
, ttype
, vals
, spec
, espec
):
395 _
, writer_name
, is_container
= self
._ttype
_handlers
(ttype
, espec
)
396 writer_func
= getattr(self
, writer_name
)
397 write
= (lambda v
: writer_func(v
, espec
)) if is_container
else writer_func
401 def writeFieldByTType(self
, ttype
, val
, spec
):
402 next(self
._write
_by
_ttype
(ttype
, [val
], spec
, spec
))
405 def checkIntegerLimits(i
, bits
):
406 if bits
== 8 and (i
< -128 or i
> 127):
407 raise TProtocolException(TProtocolException
.INVALID_DATA
,
408 "i8 requires -128 <= number <= 127")
409 elif bits
== 16 and (i
< -32768 or i
> 32767):
410 raise TProtocolException(TProtocolException
.INVALID_DATA
,
411 "i16 requires -32768 <= number <= 32767")
412 elif bits
== 32 and (i
< -2147483648 or i
> 2147483647):
413 raise TProtocolException(TProtocolException
.INVALID_DATA
,
414 "i32 requires -2147483648 <= number <= 2147483647")
415 elif bits
== 64 and (i
< -9223372036854775808 or i
> 9223372036854775807):
416 raise TProtocolException(TProtocolException
.INVALID_DATA
,
417 "i64 requires -9223372036854775808 <= number <= 9223372036854775807")
420 class TProtocolFactory(object):
421 def getProtocol(self
, trans
):