blob: b73e3c939444b46ceace4bb99bbfc421737bdf4b [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 Sleecde2b612006-09-03 21:13:07 +000020from struct import pack, unpack
Carel Combrinka715bdf2025-10-30 07:44:21 +010021import uuid
Mark Sleecde2b612006-09-03 21:13:07 +000022
Alexandre Detiste3494e1c2025-02-19 21:53:40 +010023from .TProtocol import TType, TProtocolBase, TProtocolException, TProtocolFactory
24
Mark Sleecde2b612006-09-03 21:13:07 +000025
Bryan Duxbury69720412012-01-03 17:32:30 +000026class TBinaryProtocol(TProtocolBase):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090027 """Binary implementation of the Thrift protocol driver."""
Mark Sleecde2b612006-09-03 21:13:07 +000028
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090029 # NastyHaxx. Python 2.4+ on 32-bit machines forces hex constants to be
30 # positive, converting this into a long. If we hardcode the int value
31 # instead it'll stay in 32 bit-land.
Mark Slee9b36ef32007-10-02 04:44:48 +000032
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090033 # VERSION_MASK = 0xffff0000
34 VERSION_MASK = -65536
Mark Slee9b36ef32007-10-02 04:44:48 +000035
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090036 # VERSION_1 = 0x80010000
37 VERSION_1 = -2147418112
Mark Slee9b36ef32007-10-02 04:44:48 +000038
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090039 TYPE_MASK = 0x000000ff
Mark Slee808454e2007-06-20 21:51:57 +000040
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090041 def __init__(self, trans, strictRead=False, strictWrite=True, **kwargs):
42 TProtocolBase.__init__(self, trans)
43 self.strictRead = strictRead
44 self.strictWrite = strictWrite
45 self.string_length_limit = kwargs.get('string_length_limit', None)
46 self.container_length_limit = kwargs.get('container_length_limit', None)
Nobuaki Sukegawa7b545b52016-01-11 13:46:04 +090047
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090048 def _check_string_length(self, length):
49 self._check_length(self.string_length_limit, length)
Nobuaki Sukegawa7b545b52016-01-11 13:46:04 +090050
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090051 def _check_container_length(self, length):
52 self._check_length(self.container_length_limit, length)
Mark Sleecde2b612006-09-03 21:13:07 +000053
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090054 def writeMessageBegin(self, name, type, seqid):
55 if self.strictWrite:
56 self.writeI32(TBinaryProtocol.VERSION_1 | type)
57 self.writeString(name)
58 self.writeI32(seqid)
59 else:
60 self.writeString(name)
61 self.writeByte(type)
62 self.writeI32(seqid)
Mark Slee4ac459f2006-10-25 21:39:01 +000063
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090064 def writeMessageEnd(self):
65 pass
Mark Sleecde2b612006-09-03 21:13:07 +000066
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090067 def writeStructBegin(self, name):
68 pass
Mark Sleecde2b612006-09-03 21:13:07 +000069
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090070 def writeStructEnd(self):
71 pass
Mark Sleecde2b612006-09-03 21:13:07 +000072
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090073 def writeFieldBegin(self, name, type, id):
74 self.writeByte(type)
75 self.writeI16(id)
Mark Sleecde2b612006-09-03 21:13:07 +000076
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090077 def writeFieldEnd(self):
78 pass
Mark Sleecde2b612006-09-03 21:13:07 +000079
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090080 def writeFieldStop(self):
81 self.writeByte(TType.STOP)
Mark Sleecde2b612006-09-03 21:13:07 +000082
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090083 def writeMapBegin(self, ktype, vtype, size):
84 self.writeByte(ktype)
85 self.writeByte(vtype)
86 self.writeI32(size)
Mark Sleecde2b612006-09-03 21:13:07 +000087
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090088 def writeMapEnd(self):
89 pass
Mark Sleecde2b612006-09-03 21:13:07 +000090
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090091 def writeListBegin(self, etype, size):
92 self.writeByte(etype)
93 self.writeI32(size)
Mark Sleecde2b612006-09-03 21:13:07 +000094
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090095 def writeListEnd(self):
96 pass
Mark Sleecde2b612006-09-03 21:13:07 +000097
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090098 def writeSetBegin(self, etype, size):
99 self.writeByte(etype)
100 self.writeI32(size)
Mark Sleecde2b612006-09-03 21:13:07 +0000101
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900102 def writeSetEnd(self):
103 pass
Mark Sleecde2b612006-09-03 21:13:07 +0000104
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900105 def writeBool(self, bool):
106 if bool:
107 self.writeByte(1)
108 else:
109 self.writeByte(0)
David Reiss382fc302007-08-25 18:01:30 +0000110
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900111 def writeByte(self, byte):
112 buff = pack("!b", byte)
113 self.trans.write(buff)
Mark Sleecde2b612006-09-03 21:13:07 +0000114
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900115 def writeI16(self, i16):
116 buff = pack("!h", i16)
117 self.trans.write(buff)
Mark Sleecde2b612006-09-03 21:13:07 +0000118
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900119 def writeI32(self, i32):
120 buff = pack("!i", i32)
121 self.trans.write(buff)
David Reiss382fc302007-08-25 18:01:30 +0000122
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900123 def writeI64(self, i64):
124 buff = pack("!q", i64)
125 self.trans.write(buff)
Mark Sleecde2b612006-09-03 21:13:07 +0000126
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900127 def writeDouble(self, dub):
128 buff = pack("!d", dub)
129 self.trans.write(buff)
Mark Sleec98d0502006-09-06 02:42:25 +0000130
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900131 def writeBinary(self, str):
132 self.writeI32(len(str))
133 self.trans.write(str)
Mark Sleecde2b612006-09-03 21:13:07 +0000134
Carel Combrinka715bdf2025-10-30 07:44:21 +0100135 def writeUuid(self, uuid):
136 self.trans.write(uuid.bytes)
137
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900138 def readMessageBegin(self):
139 sz = self.readI32()
140 if sz < 0:
141 version = sz & TBinaryProtocol.VERSION_MASK
142 if version != TBinaryProtocol.VERSION_1:
143 raise TProtocolException(
144 type=TProtocolException.BAD_VERSION,
145 message='Bad version in readMessageBegin: %d' % (sz))
146 type = sz & TBinaryProtocol.TYPE_MASK
147 name = self.readString()
148 seqid = self.readI32()
149 else:
150 if self.strictRead:
151 raise TProtocolException(type=TProtocolException.BAD_VERSION,
152 message='No protocol version header')
Alexandre Detiste3494e1c2025-02-19 21:53:40 +0100153 name = self.trans.readAll(sz).decode('utf-8')
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900154 type = self.readByte()
155 seqid = self.readI32()
156 return (name, type, seqid)
Mark Sleecde2b612006-09-03 21:13:07 +0000157
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900158 def readMessageEnd(self):
159 pass
Mark Sleecde2b612006-09-03 21:13:07 +0000160
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900161 def readStructBegin(self):
162 pass
Mark Sleecde2b612006-09-03 21:13:07 +0000163
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900164 def readStructEnd(self):
165 pass
Mark Sleecde2b612006-09-03 21:13:07 +0000166
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900167 def readFieldBegin(self):
168 type = self.readByte()
169 if type == TType.STOP:
170 return (None, type, 0)
171 id = self.readI16()
172 return (None, type, id)
Mark Sleecde2b612006-09-03 21:13:07 +0000173
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900174 def readFieldEnd(self):
175 pass
Mark Sleecde2b612006-09-03 21:13:07 +0000176
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900177 def readMapBegin(self):
178 ktype = self.readByte()
179 vtype = self.readByte()
180 size = self.readI32()
181 self._check_container_length(size)
182 return (ktype, vtype, size)
Mark Sleecde2b612006-09-03 21:13:07 +0000183
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900184 def readMapEnd(self):
185 pass
Mark Sleecde2b612006-09-03 21:13:07 +0000186
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900187 def readListBegin(self):
188 etype = self.readByte()
189 size = self.readI32()
190 self._check_container_length(size)
191 return (etype, size)
Mark Sleecde2b612006-09-03 21:13:07 +0000192
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900193 def readListEnd(self):
194 pass
Mark Sleecde2b612006-09-03 21:13:07 +0000195
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900196 def readSetBegin(self):
197 etype = self.readByte()
198 size = self.readI32()
199 self._check_container_length(size)
200 return (etype, size)
Mark Sleecde2b612006-09-03 21:13:07 +0000201
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900202 def readSetEnd(self):
203 pass
Mark Sleecde2b612006-09-03 21:13:07 +0000204
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900205 def readBool(self):
206 byte = self.readByte()
207 if byte == 0:
208 return False
209 return True
Mark Sleecde2b612006-09-03 21:13:07 +0000210
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900211 def readByte(self):
212 buff = self.trans.readAll(1)
213 val, = unpack('!b', buff)
214 return val
Mark Sleecde2b612006-09-03 21:13:07 +0000215
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900216 def readI16(self):
217 buff = self.trans.readAll(2)
218 val, = unpack('!h', buff)
219 return val
Mark Sleecde2b612006-09-03 21:13:07 +0000220
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900221 def readI32(self):
222 buff = self.trans.readAll(4)
223 val, = unpack('!i', buff)
224 return val
Mark Sleecde2b612006-09-03 21:13:07 +0000225
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900226 def readI64(self):
227 buff = self.trans.readAll(8)
228 val, = unpack('!q', buff)
229 return val
Mark Sleecde2b612006-09-03 21:13:07 +0000230
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900231 def readDouble(self):
232 buff = self.trans.readAll(8)
233 val, = unpack('!d', buff)
234 return val
Mark Sleec98d0502006-09-06 02:42:25 +0000235
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900236 def readBinary(self):
237 size = self.readI32()
238 self._check_string_length(size)
239 s = self.trans.readAll(size)
240 return s
Mark Slee4ac459f2006-10-25 21:39:01 +0000241
Carel Combrinka715bdf2025-10-30 07:44:21 +0100242 def readUuid(self):
243 buff = self.trans.readAll(16)
244 val = uuid.UUID(bytes=buff)
245 return val
246
David Reiss382fc302007-08-25 18:01:30 +0000247
James E. King IIIe44f6a92019-02-07 17:11:21 -0500248class TBinaryProtocolFactory(TProtocolFactory):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900249 def __init__(self, strictRead=False, strictWrite=True, **kwargs):
250 self.strictRead = strictRead
251 self.strictWrite = strictWrite
252 self.string_length_limit = kwargs.get('string_length_limit', None)
253 self.container_length_limit = kwargs.get('container_length_limit', None)
Mark Slee808454e2007-06-20 21:51:57 +0000254
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900255 def getProtocol(self, trans):
256 prot = TBinaryProtocol(trans, self.strictRead, self.strictWrite,
257 string_length_limit=self.string_length_limit,
258 container_length_limit=self.container_length_limit)
259 return prot
David Reiss382fc302007-08-25 18:01:30 +0000260
261
262class TBinaryProtocolAccelerated(TBinaryProtocol):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900263 """C-Accelerated version of TBinaryProtocol.
David Reiss382fc302007-08-25 18:01:30 +0000264
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900265 This class does not override any of TBinaryProtocol's methods,
266 but the generated code recognizes it directly and will call into
267 our C module to do the encoding, bypassing this object entirely.
268 We inherit from TBinaryProtocol so that the normal TBinaryProtocol
269 encoding can happen if the fastbinary module doesn't work for some
270 reason. (TODO(dreiss): Make this happen sanely in more cases.)
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900271 To disable this behavior, pass fallback=False constructor argument.
David Reiss382fc302007-08-25 18:01:30 +0000272
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900273 In order to take advantage of the C module, just use
274 TBinaryProtocolAccelerated instead of TBinaryProtocol.
David Reiss382fc302007-08-25 18:01:30 +0000275
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900276 NOTE: This code was contributed by an external developer.
277 The internal Thrift team has reviewed and tested it,
278 but we cannot guarantee that it is production-ready.
279 Please feel free to report bugs and/or success stories
280 to the public mailing list.
281 """
282 pass
David Reiss382fc302007-08-25 18:01:30 +0000283
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900284 def __init__(self, *args, **kwargs):
285 fallback = kwargs.pop('fallback', True)
286 super(TBinaryProtocolAccelerated, self).__init__(*args, **kwargs)
287 try:
288 from thrift.protocol import fastbinary
289 except ImportError:
290 if not fallback:
291 raise
292 else:
293 self._fast_decode = fastbinary.decode_binary
294 self._fast_encode = fastbinary.encode_binary
295
David Reiss382fc302007-08-25 18:01:30 +0000296
James E. King IIIe44f6a92019-02-07 17:11:21 -0500297class TBinaryProtocolAcceleratedFactory(TProtocolFactory):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900298 def __init__(self,
299 string_length_limit=None,
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900300 container_length_limit=None,
301 fallback=True):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900302 self.string_length_limit = string_length_limit
303 self.container_length_limit = container_length_limit
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900304 self._fallback = fallback
Nobuaki Sukegawa7b545b52016-01-11 13:46:04 +0900305
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900306 def getProtocol(self, trans):
307 return TBinaryProtocolAccelerated(
308 trans,
309 string_length_limit=self.string_length_limit,
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900310 container_length_limit=self.container_length_limit,
311 fallback=self._fallback)