blob: 3d9c0e6e332c80f2d9aa5779691c5b08e963b7a4 [file] [log] [blame]
Roger Meierf4eec7a2011-09-11 18:16:21 +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
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +090020from .TProtocol import TType, TProtocolBase, TProtocolException, checkIntegerLimits
David Reissabafd792010-09-27 17:28:15 +000021from struct import pack, unpack
22
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +090023from ..compat import binary_to_str, str_to_binary
24
David Reissabafd792010-09-27 17:28:15 +000025__all__ = ['TCompactProtocol', 'TCompactProtocolFactory']
26
27CLEAR = 0
28FIELD_WRITE = 1
29VALUE_WRITE = 2
30CONTAINER_WRITE = 3
31BOOL_WRITE = 4
32FIELD_READ = 5
33CONTAINER_READ = 6
34VALUE_READ = 7
35BOOL_READ = 8
36
Bryan Duxbury69720412012-01-03 17:32:30 +000037
David Reissabafd792010-09-27 17:28:15 +000038def make_helper(v_from, container):
39 def helper(func):
40 def nested(self, *args, **kwargs):
41 assert self.state in (v_from, container), (self.state, v_from, container)
42 return func(self, *args, **kwargs)
43 return nested
44 return helper
45writer = make_helper(VALUE_WRITE, CONTAINER_WRITE)
46reader = make_helper(VALUE_READ, CONTAINER_READ)
47
Bryan Duxbury69720412012-01-03 17:32:30 +000048
David Reissabafd792010-09-27 17:28:15 +000049def makeZigZag(n, bits):
Konrad Grochowski93fea152014-10-02 16:29:14 +020050 checkIntegerLimits(n, bits)
David Reissabafd792010-09-27 17:28:15 +000051 return (n << 1) ^ (n >> (bits - 1))
52
Bryan Duxbury69720412012-01-03 17:32:30 +000053
David Reissabafd792010-09-27 17:28:15 +000054def fromZigZag(n):
55 return (n >> 1) ^ -(n & 1)
56
Bryan Duxbury69720412012-01-03 17:32:30 +000057
David Reissabafd792010-09-27 17:28:15 +000058def writeVarint(trans, n):
Nobuaki Sukegawa33744b02016-01-03 14:24:39 +090059 out = bytearray()
David Reissabafd792010-09-27 17:28:15 +000060 while True:
61 if n & ~0x7f == 0:
62 out.append(n)
63 break
64 else:
65 out.append((n & 0xff) | 0x80)
66 n = n >> 7
Nobuaki Sukegawa33744b02016-01-03 14:24:39 +090067 trans.write(bytes(out))
David Reissabafd792010-09-27 17:28:15 +000068
Bryan Duxbury69720412012-01-03 17:32:30 +000069
David Reissabafd792010-09-27 17:28:15 +000070def readVarint(trans):
71 result = 0
72 shift = 0
73 while True:
74 x = trans.readAll(1)
75 byte = ord(x)
76 result |= (byte & 0x7f) << shift
77 if byte >> 7 == 0:
78 return result
79 shift += 7
80
Bryan Duxbury69720412012-01-03 17:32:30 +000081
Nobuaki Sukegawab9c859a2015-12-21 01:10:25 +090082class CompactType(object):
Bryan Duxburydf4cffd2011-03-15 17:16:09 +000083 STOP = 0x00
84 TRUE = 0x01
85 FALSE = 0x02
David Reissabafd792010-09-27 17:28:15 +000086 BYTE = 0x03
87 I16 = 0x04
88 I32 = 0x05
89 I64 = 0x06
90 DOUBLE = 0x07
91 BINARY = 0x08
92 LIST = 0x09
93 SET = 0x0A
94 MAP = 0x0B
95 STRUCT = 0x0C
96
Bryan Duxburydf4cffd2011-03-15 17:16:09 +000097CTYPES = {TType.STOP: CompactType.STOP,
Bryan Duxbury69720412012-01-03 17:32:30 +000098 TType.BOOL: CompactType.TRUE, # used for collection
David Reissabafd792010-09-27 17:28:15 +000099 TType.BYTE: CompactType.BYTE,
100 TType.I16: CompactType.I16,
101 TType.I32: CompactType.I32,
102 TType.I64: CompactType.I64,
103 TType.DOUBLE: CompactType.DOUBLE,
104 TType.STRING: CompactType.BINARY,
105 TType.STRUCT: CompactType.STRUCT,
106 TType.LIST: CompactType.LIST,
107 TType.SET: CompactType.SET,
Bryan Duxburydf4cffd2011-03-15 17:16:09 +0000108 TType.MAP: CompactType.MAP
David Reissabafd792010-09-27 17:28:15 +0000109 }
110
111TTYPES = {}
112for k, v in CTYPES.items():
113 TTYPES[v] = k
114TTYPES[CompactType.FALSE] = TType.BOOL
115del k
116del v
117
Bryan Duxbury69720412012-01-03 17:32:30 +0000118
David Reissabafd792010-09-27 17:28:15 +0000119class TCompactProtocol(TProtocolBase):
Bryan Duxbury69720412012-01-03 17:32:30 +0000120 """Compact implementation of the Thrift protocol driver."""
David Reissabafd792010-09-27 17:28:15 +0000121
122 PROTOCOL_ID = 0x82
123 VERSION = 1
124 VERSION_MASK = 0x1f
125 TYPE_MASK = 0xe0
Jens Geyera86886e2014-09-17 22:25:48 +0200126 TYPE_BITS = 0x07
David Reissabafd792010-09-27 17:28:15 +0000127 TYPE_SHIFT_AMOUNT = 5
128
Nobuaki Sukegawa7b545b52016-01-11 13:46:04 +0900129 def __init__(self, trans,
130 string_length_limit=None,
131 container_length_limit=None):
David Reissabafd792010-09-27 17:28:15 +0000132 TProtocolBase.__init__(self, trans)
133 self.state = CLEAR
134 self.__last_fid = 0
135 self.__bool_fid = None
136 self.__bool_value = None
137 self.__structs = []
138 self.__containers = []
Nobuaki Sukegawa7b545b52016-01-11 13:46:04 +0900139 self.string_length_limit = string_length_limit
140 self.container_length_limit = container_length_limit
141
142 def _check_string_length(self, length):
143 self._check_length(self.string_length_limit, length)
144
145 def _check_container_length(self, length):
146 self._check_length(self.container_length_limit, length)
David Reissabafd792010-09-27 17:28:15 +0000147
148 def __writeVarint(self, n):
149 writeVarint(self.trans, n)
150
151 def writeMessageBegin(self, name, type, seqid):
152 assert self.state == CLEAR
153 self.__writeUByte(self.PROTOCOL_ID)
154 self.__writeUByte(self.VERSION | (type << self.TYPE_SHIFT_AMOUNT))
155 self.__writeVarint(seqid)
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900156 self.__writeBinary(str_to_binary(name))
David Reissabafd792010-09-27 17:28:15 +0000157 self.state = VALUE_WRITE
158
159 def writeMessageEnd(self):
160 assert self.state == VALUE_WRITE
161 self.state = CLEAR
162
163 def writeStructBegin(self, name):
164 assert self.state in (CLEAR, CONTAINER_WRITE, VALUE_WRITE), self.state
165 self.__structs.append((self.state, self.__last_fid))
166 self.state = FIELD_WRITE
167 self.__last_fid = 0
168
169 def writeStructEnd(self):
170 assert self.state == FIELD_WRITE
171 self.state, self.__last_fid = self.__structs.pop()
172
173 def writeFieldStop(self):
174 self.__writeByte(0)
175
176 def __writeFieldHeader(self, type, fid):
177 delta = fid - self.__last_fid
178 if 0 < delta <= 15:
179 self.__writeUByte(delta << 4 | type)
180 else:
181 self.__writeByte(type)
182 self.__writeI16(fid)
183 self.__last_fid = fid
184
185 def writeFieldBegin(self, name, type, fid):
186 assert self.state == FIELD_WRITE, self.state
187 if type == TType.BOOL:
188 self.state = BOOL_WRITE
189 self.__bool_fid = fid
190 else:
191 self.state = VALUE_WRITE
192 self.__writeFieldHeader(CTYPES[type], fid)
193
194 def writeFieldEnd(self):
195 assert self.state in (VALUE_WRITE, BOOL_WRITE), self.state
196 self.state = FIELD_WRITE
197
198 def __writeUByte(self, byte):
199 self.trans.write(pack('!B', byte))
200
201 def __writeByte(self, byte):
202 self.trans.write(pack('!b', byte))
203
204 def __writeI16(self, i16):
205 self.__writeVarint(makeZigZag(i16, 16))
206
207 def __writeSize(self, i32):
208 self.__writeVarint(i32)
209
210 def writeCollectionBegin(self, etype, size):
211 assert self.state in (VALUE_WRITE, CONTAINER_WRITE), self.state
212 if size <= 14:
213 self.__writeUByte(size << 4 | CTYPES[etype])
214 else:
215 self.__writeUByte(0xf0 | CTYPES[etype])
216 self.__writeSize(size)
217 self.__containers.append(self.state)
218 self.state = CONTAINER_WRITE
219 writeSetBegin = writeCollectionBegin
220 writeListBegin = writeCollectionBegin
221
222 def writeMapBegin(self, ktype, vtype, size):
223 assert self.state in (VALUE_WRITE, CONTAINER_WRITE), self.state
224 if size == 0:
225 self.__writeByte(0)
226 else:
227 self.__writeSize(size)
228 self.__writeUByte(CTYPES[ktype] << 4 | CTYPES[vtype])
229 self.__containers.append(self.state)
230 self.state = CONTAINER_WRITE
231
232 def writeCollectionEnd(self):
233 assert self.state == CONTAINER_WRITE, self.state
234 self.state = self.__containers.pop()
235 writeMapEnd = writeCollectionEnd
236 writeSetEnd = writeCollectionEnd
237 writeListEnd = writeCollectionEnd
238
239 def writeBool(self, bool):
240 if self.state == BOOL_WRITE:
Bryan Duxbury69720412012-01-03 17:32:30 +0000241 if bool:
242 ctype = CompactType.TRUE
243 else:
244 ctype = CompactType.FALSE
245 self.__writeFieldHeader(ctype, self.__bool_fid)
David Reissabafd792010-09-27 17:28:15 +0000246 elif self.state == CONTAINER_WRITE:
Bryan Duxbury69720412012-01-03 17:32:30 +0000247 if bool:
248 self.__writeByte(CompactType.TRUE)
249 else:
250 self.__writeByte(CompactType.FALSE)
David Reissabafd792010-09-27 17:28:15 +0000251 else:
Bryan Duxbury69720412012-01-03 17:32:30 +0000252 raise AssertionError("Invalid state in compact protocol")
David Reissabafd792010-09-27 17:28:15 +0000253
254 writeByte = writer(__writeByte)
255 writeI16 = writer(__writeI16)
256
257 @writer
258 def writeI32(self, i32):
259 self.__writeVarint(makeZigZag(i32, 32))
260
261 @writer
262 def writeI64(self, i64):
263 self.__writeVarint(makeZigZag(i64, 64))
264
265 @writer
266 def writeDouble(self, dub):
Roger Meier8c691fa2013-11-05 04:54:33 +0100267 self.trans.write(pack('<d', dub))
David Reissabafd792010-09-27 17:28:15 +0000268
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900269 def __writeBinary(self, s):
David Reissabafd792010-09-27 17:28:15 +0000270 self.__writeSize(len(s))
271 self.trans.write(s)
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900272 writeBinary = writer(__writeBinary)
David Reissabafd792010-09-27 17:28:15 +0000273
274 def readFieldBegin(self):
275 assert self.state == FIELD_READ, self.state
276 type = self.__readUByte()
277 if type & 0x0f == TType.STOP:
278 return (None, 0, 0)
279 delta = type >> 4
280 if delta == 0:
281 fid = self.__readI16()
282 else:
283 fid = self.__last_fid + delta
284 self.__last_fid = fid
285 type = type & 0x0f
286 if type == CompactType.TRUE:
287 self.state = BOOL_READ
288 self.__bool_value = True
289 elif type == CompactType.FALSE:
290 self.state = BOOL_READ
291 self.__bool_value = False
292 else:
293 self.state = VALUE_READ
294 return (None, self.__getTType(type), fid)
295
296 def readFieldEnd(self):
297 assert self.state in (VALUE_READ, BOOL_READ), self.state
298 self.state = FIELD_READ
299
300 def __readUByte(self):
301 result, = unpack('!B', self.trans.readAll(1))
302 return result
303
304 def __readByte(self):
305 result, = unpack('!b', self.trans.readAll(1))
306 return result
307
308 def __readVarint(self):
309 return readVarint(self.trans)
310
311 def __readZigZag(self):
312 return fromZigZag(self.__readVarint())
313
314 def __readSize(self):
315 result = self.__readVarint()
316 if result < 0:
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900317 raise TProtocolException("Length < 0")
David Reissabafd792010-09-27 17:28:15 +0000318 return result
319
320 def readMessageBegin(self):
321 assert self.state == CLEAR
322 proto_id = self.__readUByte()
323 if proto_id != self.PROTOCOL_ID:
324 raise TProtocolException(TProtocolException.BAD_VERSION,
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900325 'Bad protocol id in the message: %d' % proto_id)
David Reissabafd792010-09-27 17:28:15 +0000326 ver_type = self.__readUByte()
Jens Geyera86886e2014-09-17 22:25:48 +0200327 type = (ver_type >> self.TYPE_SHIFT_AMOUNT) & self.TYPE_BITS
David Reissabafd792010-09-27 17:28:15 +0000328 version = ver_type & self.VERSION_MASK
329 if version != self.VERSION:
330 raise TProtocolException(TProtocolException.BAD_VERSION,
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900331 'Bad version: %d (expect %d)' % (version, self.VERSION))
David Reissabafd792010-09-27 17:28:15 +0000332 seqid = self.__readVarint()
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900333 name = binary_to_str(self.__readBinary())
David Reissabafd792010-09-27 17:28:15 +0000334 return (name, type, seqid)
335
336 def readMessageEnd(self):
Bryan Duxbury59d4efd2011-03-21 17:38:22 +0000337 assert self.state == CLEAR
David Reissabafd792010-09-27 17:28:15 +0000338 assert len(self.__structs) == 0
David Reissabafd792010-09-27 17:28:15 +0000339
340 def readStructBegin(self):
341 assert self.state in (CLEAR, CONTAINER_READ, VALUE_READ), self.state
342 self.__structs.append((self.state, self.__last_fid))
343 self.state = FIELD_READ
344 self.__last_fid = 0
345
346 def readStructEnd(self):
347 assert self.state == FIELD_READ
348 self.state, self.__last_fid = self.__structs.pop()
349
350 def readCollectionBegin(self):
351 assert self.state in (VALUE_READ, CONTAINER_READ), self.state
352 size_type = self.__readUByte()
353 size = size_type >> 4
354 type = self.__getTType(size_type)
355 if size == 15:
356 size = self.__readSize()
Nobuaki Sukegawa7b545b52016-01-11 13:46:04 +0900357 self._check_container_length(size)
David Reissabafd792010-09-27 17:28:15 +0000358 self.__containers.append(self.state)
359 self.state = CONTAINER_READ
360 return type, size
361 readSetBegin = readCollectionBegin
362 readListBegin = readCollectionBegin
363
364 def readMapBegin(self):
365 assert self.state in (VALUE_READ, CONTAINER_READ), self.state
366 size = self.__readSize()
Nobuaki Sukegawa7b545b52016-01-11 13:46:04 +0900367 self._check_container_length(size)
David Reissabafd792010-09-27 17:28:15 +0000368 types = 0
369 if size > 0:
370 types = self.__readUByte()
371 vtype = self.__getTType(types)
372 ktype = self.__getTType(types >> 4)
373 self.__containers.append(self.state)
374 self.state = CONTAINER_READ
375 return (ktype, vtype, size)
376
377 def readCollectionEnd(self):
378 assert self.state == CONTAINER_READ, self.state
379 self.state = self.__containers.pop()
380 readSetEnd = readCollectionEnd
381 readListEnd = readCollectionEnd
382 readMapEnd = readCollectionEnd
383
384 def readBool(self):
385 if self.state == BOOL_READ:
Bryan Duxbury54df97c2011-07-13 18:11:29 +0000386 return self.__bool_value == CompactType.TRUE
David Reissabafd792010-09-27 17:28:15 +0000387 elif self.state == CONTAINER_READ:
Bryan Duxbury54df97c2011-07-13 18:11:29 +0000388 return self.__readByte() == CompactType.TRUE
David Reissabafd792010-09-27 17:28:15 +0000389 else:
Bryan Duxbury69720412012-01-03 17:32:30 +0000390 raise AssertionError("Invalid state in compact protocol: %d" %
391 self.state)
David Reissabafd792010-09-27 17:28:15 +0000392
393 readByte = reader(__readByte)
394 __readI16 = __readZigZag
395 readI16 = reader(__readZigZag)
396 readI32 = reader(__readZigZag)
397 readI64 = reader(__readZigZag)
398
399 @reader
400 def readDouble(self):
401 buff = self.trans.readAll(8)
Roger Meier8c691fa2013-11-05 04:54:33 +0100402 val, = unpack('<d', buff)
David Reissabafd792010-09-27 17:28:15 +0000403 return val
404
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900405 def __readBinary(self):
Nobuaki Sukegawa7b545b52016-01-11 13:46:04 +0900406 size = self.__readSize()
407 self._check_string_length(size)
408 return self.trans.readAll(size)
Nobuaki Sukegawa760511f2015-11-06 21:24:16 +0900409 readBinary = reader(__readBinary)
David Reissabafd792010-09-27 17:28:15 +0000410
411 def __getTType(self, byte):
412 return TTYPES[byte & 0x0f]
413
414
Nobuaki Sukegawab9c859a2015-12-21 01:10:25 +0900415class TCompactProtocolFactory(object):
Nobuaki Sukegawa7b545b52016-01-11 13:46:04 +0900416 def __init__(self,
417 string_length_limit=None,
418 container_length_limit=None):
419 self.string_length_limit = string_length_limit
420 self.container_length_limit = container_length_limit
David Reissabafd792010-09-27 17:28:15 +0000421
422 def getProtocol(self, trans):
Nobuaki Sukegawa7b545b52016-01-11 13:46:04 +0900423 return TCompactProtocol(trans,
424 self.string_length_limit,
425 self.container_length_limit)