blob: 40e05b10dfd2840d7e2e7cd0f1aad45b4212d684 [file] [log] [blame]
Mark Slee89e2bb82007-03-01 00:20:36 +00001#
David Reissea2cba82009-03-30 21:35:00 +00002# 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#
Mark Slee89e2bb82007-03-01 00:20:36 +000019
Mark Sleee74306a2007-02-21 05:38:12 +000020from thrift.Thrift import *
Mark Sleecde2b612006-09-03 21:13:07 +000021
Mark Slee92195ae2007-02-21 05:16:30 +000022
Bryan Duxbury69720412012-01-03 17:32:30 +000023class TProtocolException(TException):
Mark Slee92195ae2007-02-21 05:16:30 +000024 """Custom Protocol Exception class"""
25
26 UNKNOWN = 0
27 INVALID_DATA = 1
28 NEGATIVE_SIZE = 2
29 SIZE_LIMIT = 3
Mark Slee808454e2007-06-20 21:51:57 +000030 BAD_VERSION = 4
Jens Geyer6d1a83a2014-05-03 00:49:05 +020031 NOT_IMPLEMENTED = 5
32 DEPTH_LIMIT = 6
Mark Slee92195ae2007-02-21 05:16:30 +000033
34 def __init__(self, type=UNKNOWN, message=None):
35 TException.__init__(self, message)
36 self.type = type
37
Mark Sleecde2b612006-09-03 21:13:07 +000038
Bryan Duxbury69720412012-01-03 17:32:30 +000039class TProtocolBase:
Mark Sleecde2b612006-09-03 21:13:07 +000040 """Base class for Thrift protocol driver."""
41
Aditya Agarwal5c468192007-02-06 01:14:33 +000042 def __init__(self, trans):
43 self.trans = trans
Mark Slee4ac459f2006-10-25 21:39:01 +000044
Roger Meierad8154a2012-12-18 21:02:16 +010045 def writeMessageBegin(self, name, ttype, seqid):
Mark Sleecde2b612006-09-03 21:13:07 +000046 pass
47
Mark Slee4ac459f2006-10-25 21:39:01 +000048 def writeMessageEnd(self):
Mark Sleecde2b612006-09-03 21:13:07 +000049 pass
50
Mark Slee4ac459f2006-10-25 21:39:01 +000051 def writeStructBegin(self, name):
Mark Sleecde2b612006-09-03 21:13:07 +000052 pass
53
Mark Slee4ac459f2006-10-25 21:39:01 +000054 def writeStructEnd(self):
Mark Sleecde2b612006-09-03 21:13:07 +000055 pass
56
Roger Meierad8154a2012-12-18 21:02:16 +010057 def writeFieldBegin(self, name, ttype, fid):
Mark Sleecde2b612006-09-03 21:13:07 +000058 pass
59
Mark Slee4ac459f2006-10-25 21:39:01 +000060 def writeFieldEnd(self):
Mark Sleecde2b612006-09-03 21:13:07 +000061 pass
62
Mark Slee4ac459f2006-10-25 21:39:01 +000063 def writeFieldStop(self):
Mark Sleecde2b612006-09-03 21:13:07 +000064 pass
65
Mark Slee4ac459f2006-10-25 21:39:01 +000066 def writeMapBegin(self, ktype, vtype, size):
Mark Sleecde2b612006-09-03 21:13:07 +000067 pass
68
Mark Slee4ac459f2006-10-25 21:39:01 +000069 def writeMapEnd(self):
Mark Sleecde2b612006-09-03 21:13:07 +000070 pass
71
Mark Slee4ac459f2006-10-25 21:39:01 +000072 def writeListBegin(self, etype, size):
Mark Sleecde2b612006-09-03 21:13:07 +000073 pass
74
Mark Slee4ac459f2006-10-25 21:39:01 +000075 def writeListEnd(self):
Mark Sleecde2b612006-09-03 21:13:07 +000076 pass
77
Mark Slee4ac459f2006-10-25 21:39:01 +000078 def writeSetBegin(self, etype, size):
Mark Sleecde2b612006-09-03 21:13:07 +000079 pass
80
Mark Slee4ac459f2006-10-25 21:39:01 +000081 def writeSetEnd(self):
Mark Sleecde2b612006-09-03 21:13:07 +000082 pass
83
Roger Meierad8154a2012-12-18 21:02:16 +010084 def writeBool(self, bool_val):
Mark Sleecde2b612006-09-03 21:13:07 +000085 pass
86
Mark Slee4ac459f2006-10-25 21:39:01 +000087 def writeByte(self, byte):
Mark Sleecde2b612006-09-03 21:13:07 +000088 pass
89
Mark Slee4ac459f2006-10-25 21:39:01 +000090 def writeI16(self, i16):
Mark Sleecde2b612006-09-03 21:13:07 +000091 pass
92
Mark Slee4ac459f2006-10-25 21:39:01 +000093 def writeI32(self, i32):
Mark Sleecde2b612006-09-03 21:13:07 +000094 pass
95
Mark Slee4ac459f2006-10-25 21:39:01 +000096 def writeI64(self, i64):
Mark Sleecde2b612006-09-03 21:13:07 +000097 pass
98
Mark Slee4ac459f2006-10-25 21:39:01 +000099 def writeDouble(self, dub):
Mark Sleec98d0502006-09-06 02:42:25 +0000100 pass
101
Roger Meierad8154a2012-12-18 21:02:16 +0100102 def writeString(self, str_val):
Mark Sleecde2b612006-09-03 21:13:07 +0000103 pass
104
Mark Slee4ac459f2006-10-25 21:39:01 +0000105 def readMessageBegin(self):
Mark Sleecde2b612006-09-03 21:13:07 +0000106 pass
107
Mark Slee4ac459f2006-10-25 21:39:01 +0000108 def readMessageEnd(self):
Mark Sleecde2b612006-09-03 21:13:07 +0000109 pass
110
Mark Slee4ac459f2006-10-25 21:39:01 +0000111 def readStructBegin(self):
Mark Sleecde2b612006-09-03 21:13:07 +0000112 pass
113
Mark Slee4ac459f2006-10-25 21:39:01 +0000114 def readStructEnd(self):
Mark Sleecde2b612006-09-03 21:13:07 +0000115 pass
116
Mark Slee4ac459f2006-10-25 21:39:01 +0000117 def readFieldBegin(self):
Mark Sleecde2b612006-09-03 21:13:07 +0000118 pass
119
Mark Slee4ac459f2006-10-25 21:39:01 +0000120 def readFieldEnd(self):
Mark Sleecde2b612006-09-03 21:13:07 +0000121 pass
122
Mark Slee4ac459f2006-10-25 21:39:01 +0000123 def readMapBegin(self):
Mark Sleecde2b612006-09-03 21:13:07 +0000124 pass
125
Mark Slee4ac459f2006-10-25 21:39:01 +0000126 def readMapEnd(self):
Mark Sleecde2b612006-09-03 21:13:07 +0000127 pass
128
Mark Slee4ac459f2006-10-25 21:39:01 +0000129 def readListBegin(self):
Mark Sleecde2b612006-09-03 21:13:07 +0000130 pass
131
Mark Slee4ac459f2006-10-25 21:39:01 +0000132 def readListEnd(self):
Mark Sleecde2b612006-09-03 21:13:07 +0000133 pass
134
Mark Slee4ac459f2006-10-25 21:39:01 +0000135 def readSetBegin(self):
Mark Sleecde2b612006-09-03 21:13:07 +0000136 pass
137
Mark Slee4ac459f2006-10-25 21:39:01 +0000138 def readSetEnd(self):
Mark Sleecde2b612006-09-03 21:13:07 +0000139 pass
140
Mark Slee4ac459f2006-10-25 21:39:01 +0000141 def readBool(self):
Mark Sleecde2b612006-09-03 21:13:07 +0000142 pass
143
Mark Slee4ac459f2006-10-25 21:39:01 +0000144 def readByte(self):
Mark Sleecde2b612006-09-03 21:13:07 +0000145 pass
146
Mark Slee4ac459f2006-10-25 21:39:01 +0000147 def readI16(self):
Mark Sleecde2b612006-09-03 21:13:07 +0000148 pass
149
Mark Slee4ac459f2006-10-25 21:39:01 +0000150 def readI32(self):
Mark Sleecde2b612006-09-03 21:13:07 +0000151 pass
152
Mark Slee4ac459f2006-10-25 21:39:01 +0000153 def readI64(self):
Mark Sleecde2b612006-09-03 21:13:07 +0000154 pass
155
Mark Slee4ac459f2006-10-25 21:39:01 +0000156 def readDouble(self):
Mark Sleec98d0502006-09-06 02:42:25 +0000157 pass
158
Mark Slee4ac459f2006-10-25 21:39:01 +0000159 def readString(self):
Mark Sleecde2b612006-09-03 21:13:07 +0000160 pass
161
Roger Meierad8154a2012-12-18 21:02:16 +0100162 def skip(self, ttype):
163 if ttype == TType.STOP:
Mark Sleecde2b612006-09-03 21:13:07 +0000164 return
Roger Meierad8154a2012-12-18 21:02:16 +0100165 elif ttype == TType.BOOL:
Mark Slee4ac459f2006-10-25 21:39:01 +0000166 self.readBool()
Roger Meierad8154a2012-12-18 21:02:16 +0100167 elif ttype == TType.BYTE:
Mark Slee4ac459f2006-10-25 21:39:01 +0000168 self.readByte()
Roger Meierad8154a2012-12-18 21:02:16 +0100169 elif ttype == TType.I16:
Mark Slee4ac459f2006-10-25 21:39:01 +0000170 self.readI16()
Roger Meierad8154a2012-12-18 21:02:16 +0100171 elif ttype == TType.I32:
Mark Slee4ac459f2006-10-25 21:39:01 +0000172 self.readI32()
Roger Meierad8154a2012-12-18 21:02:16 +0100173 elif ttype == TType.I64:
Mark Slee4ac459f2006-10-25 21:39:01 +0000174 self.readI64()
Roger Meierad8154a2012-12-18 21:02:16 +0100175 elif ttype == TType.DOUBLE:
Mark Slee4ac459f2006-10-25 21:39:01 +0000176 self.readDouble()
Roger Meierad8154a2012-12-18 21:02:16 +0100177 elif ttype == TType.STRING:
Mark Slee4ac459f2006-10-25 21:39:01 +0000178 self.readString()
Roger Meierad8154a2012-12-18 21:02:16 +0100179 elif ttype == TType.STRUCT:
Mark Slee4ac459f2006-10-25 21:39:01 +0000180 name = self.readStructBegin()
Mark Sleecde2b612006-09-03 21:13:07 +0000181 while True:
Roger Meierad8154a2012-12-18 21:02:16 +0100182 (name, ttype, id) = self.readFieldBegin()
183 if ttype == TType.STOP:
Mark Sleecde2b612006-09-03 21:13:07 +0000184 break
Roger Meierad8154a2012-12-18 21:02:16 +0100185 self.skip(ttype)
Mark Slee4ac459f2006-10-25 21:39:01 +0000186 self.readFieldEnd()
187 self.readStructEnd()
Roger Meierad8154a2012-12-18 21:02:16 +0100188 elif ttype == TType.MAP:
Mark Slee4ac459f2006-10-25 21:39:01 +0000189 (ktype, vtype, size) = self.readMapBegin()
Roger Meierad8154a2012-12-18 21:02:16 +0100190 for i in xrange(size):
Mark Slee4ac459f2006-10-25 21:39:01 +0000191 self.skip(ktype)
192 self.skip(vtype)
193 self.readMapEnd()
Roger Meierad8154a2012-12-18 21:02:16 +0100194 elif ttype == TType.SET:
Mark Slee4ac459f2006-10-25 21:39:01 +0000195 (etype, size) = self.readSetBegin()
Roger Meierad8154a2012-12-18 21:02:16 +0100196 for i in xrange(size):
Mark Slee4ac459f2006-10-25 21:39:01 +0000197 self.skip(etype)
198 self.readSetEnd()
Roger Meierad8154a2012-12-18 21:02:16 +0100199 elif ttype == TType.LIST:
Mark Slee4ac459f2006-10-25 21:39:01 +0000200 (etype, size) = self.readListBegin()
Roger Meierad8154a2012-12-18 21:02:16 +0100201 for i in xrange(size):
Mark Slee4ac459f2006-10-25 21:39:01 +0000202 self.skip(etype)
203 self.readListEnd()
Mark Sleecde2b612006-09-03 21:13:07 +0000204
Bryan Duxbury69720412012-01-03 17:32:30 +0000205 # tuple of: ( 'reader method' name, is_container bool, 'writer_method' name )
Roger Meierf4eec7a2011-09-11 18:16:21 +0000206 _TTYPE_HANDLERS = (
Bryan Duxbury69720412012-01-03 17:32:30 +0000207 (None, None, False), # 0 TType.STOP
208 (None, None, False), # 1 TType.VOID # TODO: handle void?
209 ('readBool', 'writeBool', False), # 2 TType.BOOL
210 ('readByte', 'writeByte', False), # 3 TType.BYTE and I08
211 ('readDouble', 'writeDouble', False), # 4 TType.DOUBLE
212 (None, None, False), # 5 undefined
213 ('readI16', 'writeI16', False), # 6 TType.I16
214 (None, None, False), # 7 undefined
215 ('readI32', 'writeI32', False), # 8 TType.I32
216 (None, None, False), # 9 undefined
217 ('readI64', 'writeI64', False), # 10 TType.I64
218 ('readString', 'writeString', False), # 11 TType.STRING and UTF7
219 ('readContainerStruct', 'writeContainerStruct', True), # 12 *.STRUCT
220 ('readContainerMap', 'writeContainerMap', True), # 13 TType.MAP
221 ('readContainerSet', 'writeContainerSet', True), # 14 TType.SET
222 ('readContainerList', 'writeContainerList', True), # 15 TType.LIST
223 (None, None, False), # 16 TType.UTF8 # TODO: handle utf8 types?
224 (None, None, False) # 17 TType.UTF16 # TODO: handle utf16 types?
Roger Meierf4eec7a2011-09-11 18:16:21 +0000225 )
226
227 def readFieldByTType(self, ttype, spec):
228 try:
229 (r_handler, w_handler, is_container) = self._TTYPE_HANDLERS[ttype]
230 except IndexError:
231 raise TProtocolException(type=TProtocolException.INVALID_DATA,
232 message='Invalid field type %d' % (ttype))
233 if r_handler is None:
234 raise TProtocolException(type=TProtocolException.INVALID_DATA,
235 message='Invalid field type %d' % (ttype))
236 reader = getattr(self, r_handler)
237 if not is_container:
238 return reader()
239 return reader(spec)
240
241 def readContainerList(self, spec):
242 results = []
243 ttype, tspec = spec[0], spec[1]
244 r_handler = self._TTYPE_HANDLERS[ttype][0]
245 reader = getattr(self, r_handler)
246 (list_type, list_len) = self.readListBegin()
247 if tspec is None:
248 # list values are simple types
249 for idx in xrange(list_len):
250 results.append(reader())
251 else:
252 # this is like an inlined readFieldByTType
253 container_reader = self._TTYPE_HANDLERS[list_type][0]
254 val_reader = getattr(self, container_reader)
255 for idx in xrange(list_len):
256 val = val_reader(tspec)
257 results.append(val)
258 self.readListEnd()
259 return results
260
261 def readContainerSet(self, spec):
262 results = set()
263 ttype, tspec = spec[0], spec[1]
264 r_handler = self._TTYPE_HANDLERS[ttype][0]
265 reader = getattr(self, r_handler)
266 (set_type, set_len) = self.readSetBegin()
267 if tspec is None:
268 # set members are simple types
269 for idx in xrange(set_len):
270 results.add(reader())
271 else:
272 container_reader = self._TTYPE_HANDLERS[set_type][0]
273 val_reader = getattr(self, container_reader)
274 for idx in xrange(set_len):
Bryan Duxbury69720412012-01-03 17:32:30 +0000275 results.add(val_reader(tspec))
Roger Meierf4eec7a2011-09-11 18:16:21 +0000276 self.readSetEnd()
277 return results
278
279 def readContainerStruct(self, spec):
280 (obj_class, obj_spec) = spec
281 obj = obj_class()
282 obj.read(self)
283 return obj
Bryan Duxbury69720412012-01-03 17:32:30 +0000284
Roger Meierf4eec7a2011-09-11 18:16:21 +0000285 def readContainerMap(self, spec):
286 results = dict()
287 key_ttype, key_spec = spec[0], spec[1]
288 val_ttype, val_spec = spec[2], spec[3]
289 (map_ktype, map_vtype, map_len) = self.readMapBegin()
Bryan Duxbury69720412012-01-03 17:32:30 +0000290 # TODO: compare types we just decoded with thrift_spec and
291 # abort/skip if types disagree
Roger Meierf4eec7a2011-09-11 18:16:21 +0000292 key_reader = getattr(self, self._TTYPE_HANDLERS[key_ttype][0])
293 val_reader = getattr(self, self._TTYPE_HANDLERS[val_ttype][0])
294 # list values are simple types
295 for idx in xrange(map_len):
296 if key_spec is None:
297 k_val = key_reader()
298 else:
299 k_val = self.readFieldByTType(key_ttype, key_spec)
300 if val_spec is None:
301 v_val = val_reader()
302 else:
303 v_val = self.readFieldByTType(val_ttype, val_spec)
Bryan Duxbury69720412012-01-03 17:32:30 +0000304 # this raises a TypeError with unhashable keys types
305 # i.e. this fails: d=dict(); d[[0,1]] = 2
Roger Meierf4eec7a2011-09-11 18:16:21 +0000306 results[k_val] = v_val
307 self.readMapEnd()
308 return results
309
310 def readStruct(self, obj, thrift_spec):
311 self.readStructBegin()
312 while True:
313 (fname, ftype, fid) = self.readFieldBegin()
314 if ftype == TType.STOP:
315 break
316 try:
317 field = thrift_spec[fid]
318 except IndexError:
319 self.skip(ftype)
320 else:
321 if field is not None and ftype == field[1]:
322 fname = field[2]
323 fspec = field[3]
324 val = self.readFieldByTType(ftype, fspec)
325 setattr(obj, fname, val)
326 else:
327 self.skip(ftype)
328 self.readFieldEnd()
329 self.readStructEnd()
330
331 def writeContainerStruct(self, val, spec):
332 val.write(self)
333
334 def writeContainerList(self, val, spec):
335 self.writeListBegin(spec[0], len(val))
Bryan Duxbury69720412012-01-03 17:32:30 +0000336 r_handler, w_handler, is_container = self._TTYPE_HANDLERS[spec[0]]
Roger Meierf4eec7a2011-09-11 18:16:21 +0000337 e_writer = getattr(self, w_handler)
338 if not is_container:
339 for elem in val:
340 e_writer(elem)
341 else:
342 for elem in val:
343 e_writer(elem, spec[1])
344 self.writeListEnd()
345
346 def writeContainerSet(self, val, spec):
347 self.writeSetBegin(spec[0], len(val))
348 r_handler, w_handler, is_container = self._TTYPE_HANDLERS[spec[0]]
349 e_writer = getattr(self, w_handler)
350 if not is_container:
351 for elem in val:
352 e_writer(elem)
353 else:
354 for elem in val:
355 e_writer(elem, spec[1])
356 self.writeSetEnd()
357
358 def writeContainerMap(self, val, spec):
359 k_type = spec[0]
360 v_type = spec[2]
361 ignore, ktype_name, k_is_container = self._TTYPE_HANDLERS[k_type]
362 ignore, vtype_name, v_is_container = self._TTYPE_HANDLERS[v_type]
363 k_writer = getattr(self, ktype_name)
364 v_writer = getattr(self, vtype_name)
365 self.writeMapBegin(k_type, v_type, len(val))
366 for m_key, m_val in val.iteritems():
367 if not k_is_container:
368 k_writer(m_key)
369 else:
370 k_writer(m_key, spec[1])
371 if not v_is_container:
372 v_writer(m_val)
373 else:
374 v_writer(m_val, spec[3])
375 self.writeMapEnd()
376
377 def writeStruct(self, obj, thrift_spec):
378 self.writeStructBegin(obj.__class__.__name__)
379 for field in thrift_spec:
380 if field is None:
381 continue
382 fname = field[2]
383 val = getattr(obj, fname)
384 if val is None:
385 # skip writing out unset fields
386 continue
387 fid = field[0]
388 ftype = field[1]
389 fspec = field[3]
390 # get the writer method for this value
391 self.writeFieldBegin(fname, ftype, fid)
392 self.writeFieldByTType(ftype, val, fspec)
393 self.writeFieldEnd()
394 self.writeFieldStop()
395 self.writeStructEnd()
396
397 def writeFieldByTType(self, ttype, val, spec):
398 r_handler, w_handler, is_container = self._TTYPE_HANDLERS[ttype]
399 writer = getattr(self, w_handler)
400 if is_container:
401 writer(val, spec)
402 else:
403 writer(val)
404
Bryan Duxbury69720412012-01-03 17:32:30 +0000405
Mark Slee4ac459f2006-10-25 21:39:01 +0000406class TProtocolFactory:
Aditya Agarwal5c468192007-02-06 01:14:33 +0000407 def getProtocol(self, trans):
Mark Slee4ac459f2006-10-25 21:39:01 +0000408 pass