blob: e59e0dcbdb6d19b80854f77106f7beabcfaddd05 [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
James E. King IIIe44f6a92019-02-07 17:11:21 -050020from .TProtocol import TType, TProtocolBase, TProtocolException, TProtocolFactory
bwangelme58000cc2023-11-06 12:21:38 +080021from ..compat import binary_to_str
Mark Sleecde2b612006-09-03 21:13:07 +000022from struct import pack, unpack
23
Mark Sleecde2b612006-09-03 21:13:07 +000024
Bryan Duxbury69720412012-01-03 17:32:30 +000025class TBinaryProtocol(TProtocolBase):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090026 """Binary implementation of the Thrift protocol driver."""
Mark Sleecde2b612006-09-03 21:13:07 +000027
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090028 # NastyHaxx. Python 2.4+ on 32-bit machines forces hex constants to be
29 # positive, converting this into a long. If we hardcode the int value
30 # instead it'll stay in 32 bit-land.
Mark Slee9b36ef32007-10-02 04:44:48 +000031
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090032 # VERSION_MASK = 0xffff0000
33 VERSION_MASK = -65536
Mark Slee9b36ef32007-10-02 04:44:48 +000034
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090035 # VERSION_1 = 0x80010000
36 VERSION_1 = -2147418112
Mark Slee9b36ef32007-10-02 04:44:48 +000037
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090038 TYPE_MASK = 0x000000ff
Mark Slee808454e2007-06-20 21:51:57 +000039
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090040 def __init__(self, trans, strictRead=False, strictWrite=True, **kwargs):
41 TProtocolBase.__init__(self, trans)
42 self.strictRead = strictRead
43 self.strictWrite = strictWrite
44 self.string_length_limit = kwargs.get('string_length_limit', None)
45 self.container_length_limit = kwargs.get('container_length_limit', None)
Nobuaki Sukegawa7b545b52016-01-11 13:46:04 +090046
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090047 def _check_string_length(self, length):
48 self._check_length(self.string_length_limit, length)
Nobuaki Sukegawa7b545b52016-01-11 13:46:04 +090049
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090050 def _check_container_length(self, length):
51 self._check_length(self.container_length_limit, length)
Mark Sleecde2b612006-09-03 21:13:07 +000052
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090053 def writeMessageBegin(self, name, type, seqid):
54 if self.strictWrite:
55 self.writeI32(TBinaryProtocol.VERSION_1 | type)
56 self.writeString(name)
57 self.writeI32(seqid)
58 else:
59 self.writeString(name)
60 self.writeByte(type)
61 self.writeI32(seqid)
Mark Slee4ac459f2006-10-25 21:39:01 +000062
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090063 def writeMessageEnd(self):
64 pass
Mark Sleecde2b612006-09-03 21:13:07 +000065
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090066 def writeStructBegin(self, name):
67 pass
Mark Sleecde2b612006-09-03 21:13:07 +000068
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090069 def writeStructEnd(self):
70 pass
Mark Sleecde2b612006-09-03 21:13:07 +000071
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090072 def writeFieldBegin(self, name, type, id):
73 self.writeByte(type)
74 self.writeI16(id)
Mark Sleecde2b612006-09-03 21:13:07 +000075
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090076 def writeFieldEnd(self):
77 pass
Mark Sleecde2b612006-09-03 21:13:07 +000078
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090079 def writeFieldStop(self):
80 self.writeByte(TType.STOP)
Mark Sleecde2b612006-09-03 21:13:07 +000081
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090082 def writeMapBegin(self, ktype, vtype, size):
83 self.writeByte(ktype)
84 self.writeByte(vtype)
85 self.writeI32(size)
Mark Sleecde2b612006-09-03 21:13:07 +000086
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090087 def writeMapEnd(self):
88 pass
Mark Sleecde2b612006-09-03 21:13:07 +000089
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090090 def writeListBegin(self, etype, size):
91 self.writeByte(etype)
92 self.writeI32(size)
Mark Sleecde2b612006-09-03 21:13:07 +000093
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090094 def writeListEnd(self):
95 pass
Mark Sleecde2b612006-09-03 21:13:07 +000096
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090097 def writeSetBegin(self, etype, size):
98 self.writeByte(etype)
99 self.writeI32(size)
Mark Sleecde2b612006-09-03 21:13:07 +0000100
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900101 def writeSetEnd(self):
102 pass
Mark Sleecde2b612006-09-03 21:13:07 +0000103
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900104 def writeBool(self, bool):
105 if bool:
106 self.writeByte(1)
107 else:
108 self.writeByte(0)
David Reiss382fc302007-08-25 18:01:30 +0000109
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900110 def writeByte(self, byte):
111 buff = pack("!b", byte)
112 self.trans.write(buff)
Mark Sleecde2b612006-09-03 21:13:07 +0000113
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900114 def writeI16(self, i16):
115 buff = pack("!h", i16)
116 self.trans.write(buff)
Mark Sleecde2b612006-09-03 21:13:07 +0000117
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900118 def writeI32(self, i32):
119 buff = pack("!i", i32)
120 self.trans.write(buff)
David Reiss382fc302007-08-25 18:01:30 +0000121
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900122 def writeI64(self, i64):
123 buff = pack("!q", i64)
124 self.trans.write(buff)
Mark Sleecde2b612006-09-03 21:13:07 +0000125
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900126 def writeDouble(self, dub):
127 buff = pack("!d", dub)
128 self.trans.write(buff)
Mark Sleec98d0502006-09-06 02:42:25 +0000129
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900130 def writeBinary(self, str):
131 self.writeI32(len(str))
132 self.trans.write(str)
Mark Sleecde2b612006-09-03 21:13:07 +0000133
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900134 def readMessageBegin(self):
135 sz = self.readI32()
136 if sz < 0:
137 version = sz & TBinaryProtocol.VERSION_MASK
138 if version != TBinaryProtocol.VERSION_1:
139 raise TProtocolException(
140 type=TProtocolException.BAD_VERSION,
141 message='Bad version in readMessageBegin: %d' % (sz))
142 type = sz & TBinaryProtocol.TYPE_MASK
143 name = self.readString()
144 seqid = self.readI32()
145 else:
146 if self.strictRead:
147 raise TProtocolException(type=TProtocolException.BAD_VERSION,
148 message='No protocol version header')
bwangelme58000cc2023-11-06 12:21:38 +0800149 name = binary_to_str(self.trans.readAll(sz))
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900150 type = self.readByte()
151 seqid = self.readI32()
152 return (name, type, seqid)
Mark Sleecde2b612006-09-03 21:13:07 +0000153
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900154 def readMessageEnd(self):
155 pass
Mark Sleecde2b612006-09-03 21:13:07 +0000156
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900157 def readStructBegin(self):
158 pass
Mark Sleecde2b612006-09-03 21:13:07 +0000159
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900160 def readStructEnd(self):
161 pass
Mark Sleecde2b612006-09-03 21:13:07 +0000162
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900163 def readFieldBegin(self):
164 type = self.readByte()
165 if type == TType.STOP:
166 return (None, type, 0)
167 id = self.readI16()
168 return (None, type, id)
Mark Sleecde2b612006-09-03 21:13:07 +0000169
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900170 def readFieldEnd(self):
171 pass
Mark Sleecde2b612006-09-03 21:13:07 +0000172
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900173 def readMapBegin(self):
174 ktype = self.readByte()
175 vtype = self.readByte()
176 size = self.readI32()
177 self._check_container_length(size)
178 return (ktype, vtype, size)
Mark Sleecde2b612006-09-03 21:13:07 +0000179
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900180 def readMapEnd(self):
181 pass
Mark Sleecde2b612006-09-03 21:13:07 +0000182
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900183 def readListBegin(self):
184 etype = self.readByte()
185 size = self.readI32()
186 self._check_container_length(size)
187 return (etype, size)
Mark Sleecde2b612006-09-03 21:13:07 +0000188
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900189 def readListEnd(self):
190 pass
Mark Sleecde2b612006-09-03 21:13:07 +0000191
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900192 def readSetBegin(self):
193 etype = self.readByte()
194 size = self.readI32()
195 self._check_container_length(size)
196 return (etype, size)
Mark Sleecde2b612006-09-03 21:13:07 +0000197
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900198 def readSetEnd(self):
199 pass
Mark Sleecde2b612006-09-03 21:13:07 +0000200
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900201 def readBool(self):
202 byte = self.readByte()
203 if byte == 0:
204 return False
205 return True
Mark Sleecde2b612006-09-03 21:13:07 +0000206
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900207 def readByte(self):
208 buff = self.trans.readAll(1)
209 val, = unpack('!b', buff)
210 return val
Mark Sleecde2b612006-09-03 21:13:07 +0000211
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900212 def readI16(self):
213 buff = self.trans.readAll(2)
214 val, = unpack('!h', buff)
215 return val
Mark Sleecde2b612006-09-03 21:13:07 +0000216
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900217 def readI32(self):
218 buff = self.trans.readAll(4)
219 val, = unpack('!i', buff)
220 return val
Mark Sleecde2b612006-09-03 21:13:07 +0000221
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900222 def readI64(self):
223 buff = self.trans.readAll(8)
224 val, = unpack('!q', buff)
225 return val
Mark Sleecde2b612006-09-03 21:13:07 +0000226
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900227 def readDouble(self):
228 buff = self.trans.readAll(8)
229 val, = unpack('!d', buff)
230 return val
Mark Sleec98d0502006-09-06 02:42:25 +0000231
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900232 def readBinary(self):
233 size = self.readI32()
234 self._check_string_length(size)
235 s = self.trans.readAll(size)
236 return s
Mark Slee4ac459f2006-10-25 21:39:01 +0000237
David Reiss382fc302007-08-25 18:01:30 +0000238
James E. King IIIe44f6a92019-02-07 17:11:21 -0500239class TBinaryProtocolFactory(TProtocolFactory):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900240 def __init__(self, strictRead=False, strictWrite=True, **kwargs):
241 self.strictRead = strictRead
242 self.strictWrite = strictWrite
243 self.string_length_limit = kwargs.get('string_length_limit', None)
244 self.container_length_limit = kwargs.get('container_length_limit', None)
Mark Slee808454e2007-06-20 21:51:57 +0000245
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900246 def getProtocol(self, trans):
247 prot = TBinaryProtocol(trans, self.strictRead, self.strictWrite,
248 string_length_limit=self.string_length_limit,
249 container_length_limit=self.container_length_limit)
250 return prot
David Reiss382fc302007-08-25 18:01:30 +0000251
252
253class TBinaryProtocolAccelerated(TBinaryProtocol):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900254 """C-Accelerated version of TBinaryProtocol.
David Reiss382fc302007-08-25 18:01:30 +0000255
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900256 This class does not override any of TBinaryProtocol's methods,
257 but the generated code recognizes it directly and will call into
258 our C module to do the encoding, bypassing this object entirely.
259 We inherit from TBinaryProtocol so that the normal TBinaryProtocol
260 encoding can happen if the fastbinary module doesn't work for some
261 reason. (TODO(dreiss): Make this happen sanely in more cases.)
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900262 To disable this behavior, pass fallback=False constructor argument.
David Reiss382fc302007-08-25 18:01:30 +0000263
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900264 In order to take advantage of the C module, just use
265 TBinaryProtocolAccelerated instead of TBinaryProtocol.
David Reiss382fc302007-08-25 18:01:30 +0000266
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900267 NOTE: This code was contributed by an external developer.
268 The internal Thrift team has reviewed and tested it,
269 but we cannot guarantee that it is production-ready.
270 Please feel free to report bugs and/or success stories
271 to the public mailing list.
272 """
273 pass
David Reiss382fc302007-08-25 18:01:30 +0000274
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900275 def __init__(self, *args, **kwargs):
276 fallback = kwargs.pop('fallback', True)
277 super(TBinaryProtocolAccelerated, self).__init__(*args, **kwargs)
278 try:
279 from thrift.protocol import fastbinary
280 except ImportError:
281 if not fallback:
282 raise
283 else:
284 self._fast_decode = fastbinary.decode_binary
285 self._fast_encode = fastbinary.encode_binary
286
David Reiss382fc302007-08-25 18:01:30 +0000287
James E. King IIIe44f6a92019-02-07 17:11:21 -0500288class TBinaryProtocolAcceleratedFactory(TProtocolFactory):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900289 def __init__(self,
290 string_length_limit=None,
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900291 container_length_limit=None,
292 fallback=True):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900293 self.string_length_limit = string_length_limit
294 self.container_length_limit = container_length_limit
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900295 self._fallback = fallback
Nobuaki Sukegawa7b545b52016-01-11 13:46:04 +0900296
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900297 def getProtocol(self, trans):
298 return TBinaryProtocolAccelerated(
299 trans,
300 string_length_limit=self.string_length_limit,
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900301 container_length_limit=self.container_length_limit,
302 fallback=self._fallback)