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 TProtocol import *
21 from struct import pack, unpack
23 __all__ = ['TCompactProtocol', 'TCompactProtocolFactory']
36 def make_helper(v_from, container):
38 def nested(self, *args, **kwargs):
39 assert self.state in (v_from, container), (self.state, v_from, container)
40 return func(self, *args, **kwargs)
43 writer = make_helper(VALUE_WRITE, CONTAINER_WRITE)
44 reader = make_helper(VALUE_READ, CONTAINER_READ)
47 def makeZigZag(n, bits):
48 checkIntegerLimits(n, bits)
49 return (n << 1) ^ (n >> (bits - 1))
53 return (n >> 1) ^ -(n & 1)
56 def writeVarint(trans, n):
63 out.append((n & 0xff) | 0x80)
65 trans.write(''.join(map(chr, out)))
68 def readVarint(trans):
74 result |= (byte & 0x7f) << shift
95 CTYPES = {TType.STOP: CompactType.STOP,
96 TType.BOOL: CompactType.TRUE, # used for collection
97 TType.BYTE: CompactType.BYTE,
98 TType.I16: CompactType.I16,
99 TType.I32: CompactType.I32,
100 TType.I64: CompactType.I64,
101 TType.DOUBLE: CompactType.DOUBLE,
102 TType.STRING: CompactType.BINARY,
103 TType.STRUCT: CompactType.STRUCT,
104 TType.LIST: CompactType.LIST,
105 TType.SET: CompactType.SET,
106 TType.MAP: CompactType.MAP
110 for k, v in CTYPES.items():
112 TTYPES[CompactType.FALSE] = TType.BOOL
117 class TCompactProtocol(TProtocolBase):
118 """Compact implementation of the Thrift protocol driver."""
125 TYPE_SHIFT_AMOUNT = 5
127 def __init__(self, trans):
128 TProtocolBase.__init__(self, trans)
131 self.__bool_fid = None
132 self.__bool_value = None
134 self.__containers = []
136 def __writeVarint(self, n):
137 writeVarint(self.trans, n)
139 def writeMessageBegin(self, name, type, seqid):
140 assert self.state == CLEAR
141 self.__writeUByte(self.PROTOCOL_ID)
142 self.__writeUByte(self.VERSION | (type << self.TYPE_SHIFT_AMOUNT))
143 self.__writeVarint(seqid)
144 self.__writeString(name)
145 self.state = VALUE_WRITE
147 def writeMessageEnd(self):
148 assert self.state == VALUE_WRITE
151 def writeStructBegin(self, name):
152 assert self.state in (CLEAR, CONTAINER_WRITE, VALUE_WRITE), self.state
153 self.__structs.append((self.state, self.__last_fid))
154 self.state = FIELD_WRITE
157 def writeStructEnd(self):
158 assert self.state == FIELD_WRITE
159 self.state, self.__last_fid = self.__structs.pop()
161 def writeFieldStop(self):
164 def __writeFieldHeader(self, type, fid):
165 delta = fid - self.__last_fid
167 self.__writeUByte(delta << 4 | type)
169 self.__writeByte(type)
171 self.__last_fid = fid
173 def writeFieldBegin(self, name, type, fid):
174 assert self.state == FIELD_WRITE, self.state
175 if type == TType.BOOL:
176 self.state = BOOL_WRITE
177 self.__bool_fid = fid
179 self.state = VALUE_WRITE
180 self.__writeFieldHeader(CTYPES[type], fid)
182 def writeFieldEnd(self):
183 assert self.state in (VALUE_WRITE, BOOL_WRITE), self.state
184 self.state = FIELD_WRITE
186 def __writeUByte(self, byte):
187 self.trans.write(pack('!B', byte))
189 def __writeByte(self, byte):
190 self.trans.write(pack('!b', byte))
192 def __writeI16(self, i16):
193 self.__writeVarint(makeZigZag(i16, 16))
195 def __writeSize(self, i32):
196 self.__writeVarint(i32)
198 def writeCollectionBegin(self, etype, size):
199 assert self.state in (VALUE_WRITE, CONTAINER_WRITE), self.state
201 self.__writeUByte(size << 4 | CTYPES[etype])
203 self.__writeUByte(0xf0 | CTYPES[etype])
204 self.__writeSize(size)
205 self.__containers.append(self.state)
206 self.state = CONTAINER_WRITE
207 writeSetBegin = writeCollectionBegin
208 writeListBegin = writeCollectionBegin
210 def writeMapBegin(self, ktype, vtype, size):
211 assert self.state in (VALUE_WRITE, CONTAINER_WRITE), self.state
215 self.__writeSize(size)
216 self.__writeUByte(CTYPES[ktype] << 4 | CTYPES[vtype])
217 self.__containers.append(self.state)
218 self.state = CONTAINER_WRITE
220 def writeCollectionEnd(self):
221 assert self.state == CONTAINER_WRITE, self.state
222 self.state = self.__containers.pop()
223 writeMapEnd = writeCollectionEnd
224 writeSetEnd = writeCollectionEnd
225 writeListEnd = writeCollectionEnd
227 def writeBool(self, bool):
228 if self.state == BOOL_WRITE:
230 ctype = CompactType.TRUE
232 ctype = CompactType.FALSE
233 self.__writeFieldHeader(ctype, self.__bool_fid)
234 elif self.state == CONTAINER_WRITE:
236 self.__writeByte(CompactType.TRUE)
238 self.__writeByte(CompactType.FALSE)
240 raise AssertionError("Invalid state in compact protocol")
242 writeByte = writer(__writeByte)
243 writeI16 = writer(__writeI16)
246 def writeI32(self, i32):
247 self.__writeVarint(makeZigZag(i32, 32))
250 def writeI64(self, i64):
251 self.__writeVarint(makeZigZag(i64, 64))
254 def writeDouble(self, dub):
255 self.trans.write(pack('<d', dub))
257 def __writeString(self, s):
258 self.__writeSize(len(s))
260 writeString = writer(__writeString)
262 def readFieldBegin(self):
263 assert self.state == FIELD_READ, self.state
264 type = self.__readUByte()
265 if type & 0x0f == TType.STOP:
269 fid = self.__readI16()
271 fid = self.__last_fid + delta
272 self.__last_fid = fid
274 if type == CompactType.TRUE:
275 self.state = BOOL_READ
276 self.__bool_value = True
277 elif type == CompactType.FALSE:
278 self.state = BOOL_READ
279 self.__bool_value = False
281 self.state = VALUE_READ
282 return (None, self.__getTType(type), fid)
284 def readFieldEnd(self):
285 assert self.state in (VALUE_READ, BOOL_READ), self.state
286 self.state = FIELD_READ
288 def __readUByte(self):
289 result, = unpack('!B', self.trans.readAll(1))
292 def __readByte(self):
293 result, = unpack('!b', self.trans.readAll(1))
296 def __readVarint(self):
297 return readVarint(self.trans)
299 def __readZigZag(self):
300 return fromZigZag(self.__readVarint())
302 def __readSize(self):
303 result = self.__readVarint()
305 raise TException("Length < 0")
308 def readMessageBegin(self):
309 assert self.state == CLEAR
310 proto_id = self.__readUByte()
311 if proto_id != self.PROTOCOL_ID:
312 raise TProtocolException(TProtocolException.BAD_VERSION,
313 'Bad protocol id in the message: %d' % proto_id)
314 ver_type = self.__readUByte()
315 type = (ver_type >> self.TYPE_SHIFT_AMOUNT) & self.TYPE_BITS
316 version = ver_type & self.VERSION_MASK
317 if version != self.VERSION:
318 raise TProtocolException(TProtocolException.BAD_VERSION,
319 'Bad version: %d (expect %d)' % (version, self.VERSION))
320 seqid = self.__readVarint()
321 name = self.__readString()
322 return (name, type, seqid)
324 def readMessageEnd(self):
325 assert self.state == CLEAR
326 assert len(self.__structs) == 0
328 def readStructBegin(self):
329 assert self.state in (CLEAR, CONTAINER_READ, VALUE_READ), self.state
330 self.__structs.append((self.state, self.__last_fid))
331 self.state = FIELD_READ
334 def readStructEnd(self):
335 assert self.state == FIELD_READ
336 self.state, self.__last_fid = self.__structs.pop()
338 def readCollectionBegin(self):
339 assert self.state in (VALUE_READ, CONTAINER_READ), self.state
340 size_type = self.__readUByte()
341 size = size_type >> 4
342 type = self.__getTType(size_type)
344 size = self.__readSize()
345 self.__containers.append(self.state)
346 self.state = CONTAINER_READ
348 readSetBegin = readCollectionBegin
349 readListBegin = readCollectionBegin
351 def readMapBegin(self):
352 assert self.state in (VALUE_READ, CONTAINER_READ), self.state
353 size = self.__readSize()
356 types = self.__readUByte()
357 vtype = self.__getTType(types)
358 ktype = self.__getTType(types >> 4)
359 self.__containers.append(self.state)
360 self.state = CONTAINER_READ
361 return (ktype, vtype, size)
363 def readCollectionEnd(self):
364 assert self.state == CONTAINER_READ, self.state
365 self.state = self.__containers.pop()
366 readSetEnd = readCollectionEnd
367 readListEnd = readCollectionEnd
368 readMapEnd = readCollectionEnd
371 if self.state == BOOL_READ:
372 return self.__bool_value == CompactType.TRUE
373 elif self.state == CONTAINER_READ:
374 return self.__readByte() == CompactType.TRUE
376 raise AssertionError("Invalid state in compact protocol: %d" %
379 readByte = reader(__readByte)
380 __readI16 = __readZigZag
381 readI16 = reader(__readZigZag)
382 readI32 = reader(__readZigZag)
383 readI64 = reader(__readZigZag)
386 def readDouble(self):
387 buff = self.trans.readAll(8)
388 val, = unpack('<d', buff)
391 def __readString(self):
392 len = self.__readSize()
393 return self.trans.readAll(len)
394 readString = reader(__readString)
396 def __getTType(self, byte):
397 return TTYPES[byte & 0x0f]
400 class TCompactProtocolFactory:
404 def getProtocol(self, trans):
405 return TCompactProtocol(trans)