blob: b691c4169c7f72ab4446c725e9336168df9fcfc0 [file] [log] [blame]
David Reissea2cba82009-03-30 21:35:00 +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 */
Mark Slee9f0c6512007-02-28 23:58:26 +000019
Mark Sleef5f2be42006-09-05 21:05:31 +000020#ifndef _THRIFT_PROTOCOL_TPROTOCOL_H_
21#define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1
Mark Sleee8540632006-05-30 09:24:40 +000022
Nobuaki Sukegawa11da87e2016-09-10 14:02:19 +090023#ifdef _WIN32
24// Need to come before any Windows.h includes
Jeremiah50819ce2022-02-08 12:46:45 +010025#include <winsock2.h>
Nobuaki Sukegawa11da87e2016-09-10 14:02:19 +090026#endif
27
Roger Meier49ff8b12012-04-13 09:12:31 +000028#include <thrift/transport/TTransport.h>
29#include <thrift/protocol/TProtocolException.h>
zeshuai00786352b42020-06-15 17:00:33 +080030#include <thrift/protocol/TEnum.h>
31#include <thrift/protocol/TList.h>
32#include <thrift/protocol/TSet.h>
33#include <thrift/protocol/TMap.h>
Marc Slemko16698852006-08-04 03:16:10 +000034
cyy316723a2019-01-05 16:35:14 +080035#include <memory>
Marc Slemko16698852006-08-04 03:16:10 +000036
Roger Meier2fa9c312011-09-05 19:15:53 +000037#ifdef HAVE_NETINET_IN_H
Mark Slee8d7e1f62006-06-07 06:48:56 +000038#include <netinet/in.h>
Roger Meier2fa9c312011-09-05 19:15:53 +000039#endif
Mark Sleee8540632006-05-30 09:24:40 +000040#include <sys/types.h>
41#include <string>
42#include <map>
David Reiss8dfc7322010-10-06 17:09:58 +000043#include <vector>
Ben Craigcfaadcc2015-07-08 20:50:33 -050044#include <climits>
Mark Sleee8540632006-05-30 09:24:40 +000045
David Reisse4d4ea02009-04-02 21:37:17 +000046// Use this to get around strict aliasing rules.
47// For example, uint64_t i = bitwise_cast<uint64_t>(returns_double());
48// The most obvious implementation is to just cast a pointer,
49// but that doesn't work.
50// For a pretty in-depth explanation of the problem, see
Jens Geyer1a8e0482015-04-30 20:29:20 +020051// http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html
David Reisse4d4ea02009-04-02 21:37:17 +000052template <typename To, typename From>
53static inline To bitwise_cast(From from) {
cyy863262d2019-01-06 10:40:58 +080054 static_assert(sizeof(From) == sizeof(To), "sizeof(From) == sizeof(To)");
David Reisse4d4ea02009-04-02 21:37:17 +000055
56 // BAD!!! These are all broken with -O2.
57 //return *reinterpret_cast<To*>(&from); // BAD!!!
58 //return *static_cast<To*>(static_cast<void*>(&from)); // BAD!!!
59 //return *(To*)(void*)&from; // BAD!!!
60
61 // Super clean and paritally blessed by section 3.9 of the standard.
62 //unsigned char c[sizeof(from)];
63 //memcpy(c, &from, sizeof(from));
64 //To to;
65 //memcpy(&to, c, sizeof(c));
66 //return to;
67
68 // Slightly more questionable.
69 // Same code emitted by GCC.
70 //To to;
71 //memcpy(&to, &from, sizeof(from));
72 //return to;
73
74 // Technically undefined, but almost universally supported,
75 // and the most efficient implementation.
76 union {
77 From f;
78 To t;
79 } u;
80 u.f = from;
81 return u.t;
82}
83
84
Jake Farrellc1fe30b2011-06-01 20:34:26 +000085#ifdef HAVE_SYS_PARAM_H
Bryan Duxbury184d2622010-08-17 17:43:58 +000086#include <sys/param.h>
Mark Slee4f261c52007-04-13 00:33:24 +000087#endif
88
Roger Meierf9f841d2012-06-19 20:42:33 +000089#ifndef __THRIFT_BYTE_ORDER
Mark Slee1d2ead32007-06-09 01:23:04 +000090# if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
Roger Meierf9f841d2012-06-19 20:42:33 +000091# define __THRIFT_BYTE_ORDER BYTE_ORDER
92# define __THRIFT_LITTLE_ENDIAN LITTLE_ENDIAN
93# define __THRIFT_BIG_ENDIAN BIG_ENDIAN
Mark Slee1d2ead32007-06-09 01:23:04 +000094# else
James E. King IIIee8caca2019-05-04 08:20:59 -040095# include <boost/predef/other/endian.h>
96# if BOOST_ENDIAN_BIG_BYTE
97# define __THRIFT_BYTE_ORDER 4321
98# define __THRIFT_LITTLE_ENDIAN 0
99# define __THRIFT_BIG_ENDIAN __THRIFT_BYTE_ORDER
100# elif BOOST_ENDIAN_LITTLE_BYTE
101# define __THRIFT_BYTE_ORDER 1234
102# define __THRIFT_LITTLE_ENDIAN __THRIFT_BYTE_ORDER
103# define __THRIFT_BIG_ENDIAN 0
104# endif
Roger Meiera93848b2011-09-12 22:20:11 +0000105# ifdef BOOST_LITTLE_ENDIAN
Roger Meiera93848b2011-09-12 22:20:11 +0000106# else
Roger Meiera93848b2011-09-12 22:20:11 +0000107# endif
Mark Slee1d2ead32007-06-09 01:23:04 +0000108# endif
109#endif
110
Roger Meierf9f841d2012-06-19 20:42:33 +0000111#if __THRIFT_BYTE_ORDER == __THRIFT_BIG_ENDIAN
jfarrellad3a9552015-09-24 23:27:34 -0400112# if !defined(THRIFT_ntohll)
113# define THRIFT_ntohll(n) (n)
114# define THRIFT_htonll(n) (n)
Jim King9dfe7b82015-05-06 09:51:54 -0400115# endif
David Reisse4d4ea02009-04-02 21:37:17 +0000116# if defined(__GNUC__) && defined(__GLIBC__)
117# include <byteswap.h>
jfarrellad3a9552015-09-24 23:27:34 -0400118# define THRIFT_htolell(n) bswap_64(n)
119# define THRIFT_letohll(n) bswap_64(n)
Ben Craig384f9762015-07-08 20:33:03 -0500120# define THRIFT_htolel(n) bswap_32(n)
121# define THRIFT_letohl(n) bswap_32(n)
122# define THRIFT_htoles(n) bswap_16(n)
123# define THRIFT_letohs(n) bswap_16(n)
David Reisse4d4ea02009-04-02 21:37:17 +0000124# else /* GNUC & GLIBC */
125# define bswap_64(n) \
126 ( (((n) & 0xff00000000000000ull) >> 56) \
127 | (((n) & 0x00ff000000000000ull) >> 40) \
128 | (((n) & 0x0000ff0000000000ull) >> 24) \
129 | (((n) & 0x000000ff00000000ull) >> 8) \
130 | (((n) & 0x00000000ff000000ull) << 8) \
131 | (((n) & 0x0000000000ff0000ull) << 24) \
132 | (((n) & 0x000000000000ff00ull) << 40) \
133 | (((n) & 0x00000000000000ffull) << 56) )
Ben Craig384f9762015-07-08 20:33:03 -0500134# define bswap_32(n) \
135 ( (((n) & 0xff000000ul) >> 24) \
136 | (((n) & 0x00ff0000ul) >> 8) \
137 | (((n) & 0x0000ff00ul) << 8) \
138 | (((n) & 0x000000fful) << 24) )
139# define bswap_16(n) \
140 ( (((n) & ((unsigned short)0xff00ul)) >> 8) \
141 | (((n) & ((unsigned short)0x00fful)) << 8) )
jfarrellad3a9552015-09-24 23:27:34 -0400142# define THRIFT_htolell(n) bswap_64(n)
143# define THRIFT_letohll(n) bswap_64(n)
Ben Craig384f9762015-07-08 20:33:03 -0500144# define THRIFT_htolel(n) bswap_32(n)
145# define THRIFT_letohl(n) bswap_32(n)
146# define THRIFT_htoles(n) bswap_16(n)
147# define THRIFT_letohs(n) bswap_16(n)
David Reisse4d4ea02009-04-02 21:37:17 +0000148# endif /* GNUC & GLIBC */
Roger Meierf9f841d2012-06-19 20:42:33 +0000149#elif __THRIFT_BYTE_ORDER == __THRIFT_LITTLE_ENDIAN
jfarrellad3a9552015-09-24 23:27:34 -0400150# define THRIFT_htolell(n) (n)
151# define THRIFT_letohll(n) (n)
Ben Craig384f9762015-07-08 20:33:03 -0500152# define THRIFT_htolel(n) (n)
153# define THRIFT_letohl(n) (n)
154# define THRIFT_htoles(n) (n)
155# define THRIFT_letohs(n) (n)
Mark Slee4f261c52007-04-13 00:33:24 +0000156# if defined(__GNUC__) && defined(__GLIBC__)
157# include <byteswap.h>
jfarrellad3a9552015-09-24 23:27:34 -0400158# define THRIFT_ntohll(n) bswap_64(n)
159# define THRIFT_htonll(n) bswap_64(n)
Roger Meierb69d24d2012-10-04 18:02:15 +0000160# elif defined(_MSC_VER) /* Microsoft Visual C++ */
jfarrellad3a9552015-09-24 23:27:34 -0400161# define THRIFT_ntohll(n) ( _byteswap_uint64((uint64_t)n) )
162# define THRIFT_htonll(n) ( _byteswap_uint64((uint64_t)n) )
163# elif !defined(THRIFT_ntohll) /* Not GNUC/GLIBC or MSVC */
164# define THRIFT_ntohll(n) ( (((uint64_t)ntohl((uint32_t)n)) << 32) + ntohl((uint32_t)(n >> 32)) )
165# define THRIFT_htonll(n) ( (((uint64_t)htonl((uint32_t)n)) << 32) + htonl((uint32_t)(n >> 32)) )
Roger Meierb69d24d2012-10-04 18:02:15 +0000166# endif /* GNUC/GLIBC or MSVC or something else */
Roger Meierf9f841d2012-06-19 20:42:33 +0000167#else /* __THRIFT_BYTE_ORDER */
jfarrellad3a9552015-09-24 23:27:34 -0400168# error "Can't define THRIFT_htonll or THRIFT_ntohll!"
Mark Sleedc8a2a22006-09-19 22:20:18 +0000169#endif
Mark Slee8d7e1f62006-06-07 06:48:56 +0000170
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100171namespace apache {
172namespace thrift {
173namespace protocol {
Ben Craigf4e6e622013-11-05 19:49:12 -0600174
175using apache::thrift::transport::TTransport;
176
Mark Sleee8540632006-05-30 09:24:40 +0000177/**
178 * Abstract class for a thrift protocol driver. These are all the methods that
179 * a protocol must implement. Essentially, there must be some way of reading
180 * and writing all the base types, plus a mechanism for writing out structs
Mark Slee5d06fea2007-03-05 22:18:18 +0000181 * with indexed fields.
182 *
183 * TProtocol objects should not be shared across multiple encoding contexts,
184 * as they may need to maintain internal state in some protocols (i.e. XML).
185 * Note that is is acceptable for the TProtocol module to do its own internal
186 * buffered reads/writes to the underlying TTransport where appropriate (i.e.
187 * when parsing an input XML stream, reading should be batched rather than
188 * looking ahead character by character for a close tag).
Mark Sleee8540632006-05-30 09:24:40 +0000189 *
Mark Sleee8540632006-05-30 09:24:40 +0000190 */
191class TProtocol {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100192public:
Ben Craigcfaadcc2015-07-08 20:50:33 -0500193 virtual ~TProtocol();
Mark Sleee8540632006-05-30 09:24:40 +0000194
195 /**
Mark Slee8d7e1f62006-06-07 06:48:56 +0000196 * Writing functions.
Mark Sleee8540632006-05-30 09:24:40 +0000197 */
198
David Reiss6806fb82010-10-06 17:09:52 +0000199 virtual uint32_t writeMessageBegin_virt(const std::string& name,
200 const TMessageType messageType,
201 const int32_t seqid) = 0;
Marc Slemko16698852006-08-04 03:16:10 +0000202
David Reiss6806fb82010-10-06 17:09:52 +0000203 virtual uint32_t writeMessageEnd_virt() = 0;
Marc Slemko16698852006-08-04 03:16:10 +0000204
David Reiss6806fb82010-10-06 17:09:52 +0000205 virtual uint32_t writeStructBegin_virt(const char* name) = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000206
David Reiss6806fb82010-10-06 17:09:52 +0000207 virtual uint32_t writeStructEnd_virt() = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000208
David Reiss6806fb82010-10-06 17:09:52 +0000209 virtual uint32_t writeFieldBegin_virt(const char* name,
210 const TType fieldType,
211 const int16_t fieldId) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000212
David Reiss6806fb82010-10-06 17:09:52 +0000213 virtual uint32_t writeFieldEnd_virt() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000214
David Reiss6806fb82010-10-06 17:09:52 +0000215 virtual uint32_t writeFieldStop_virt() = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000216
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100217 virtual uint32_t writeMapBegin_virt(const TType keyType, const TType valType, const uint32_t size)
218 = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000219
David Reiss6806fb82010-10-06 17:09:52 +0000220 virtual uint32_t writeMapEnd_virt() = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000221
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100222 virtual uint32_t writeListBegin_virt(const TType elemType, const uint32_t size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000223
David Reiss6806fb82010-10-06 17:09:52 +0000224 virtual uint32_t writeListEnd_virt() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000225
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100226 virtual uint32_t writeSetBegin_virt(const TType elemType, const uint32_t size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000227
David Reiss6806fb82010-10-06 17:09:52 +0000228 virtual uint32_t writeSetEnd_virt() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000229
David Reiss6806fb82010-10-06 17:09:52 +0000230 virtual uint32_t writeBool_virt(const bool value) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000231
David Reiss6806fb82010-10-06 17:09:52 +0000232 virtual uint32_t writeByte_virt(const int8_t byte) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000233
David Reiss6806fb82010-10-06 17:09:52 +0000234 virtual uint32_t writeI16_virt(const int16_t i16) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000235
David Reiss6806fb82010-10-06 17:09:52 +0000236 virtual uint32_t writeI32_virt(const int32_t i32) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000237
David Reiss6806fb82010-10-06 17:09:52 +0000238 virtual uint32_t writeI64_virt(const int64_t i64) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000239
David Reiss6806fb82010-10-06 17:09:52 +0000240 virtual uint32_t writeDouble_virt(const double dub) = 0;
Mark Sleec98d0502006-09-06 02:42:25 +0000241
David Reiss6806fb82010-10-06 17:09:52 +0000242 virtual uint32_t writeString_virt(const std::string& str) = 0;
Mark Sleee8540632006-05-30 09:24:40 +0000243
David Reiss6806fb82010-10-06 17:09:52 +0000244 virtual uint32_t writeBinary_virt(const std::string& str) = 0;
245
246 uint32_t writeMessageBegin(const std::string& name,
247 const TMessageType messageType,
248 const int32_t seqid) {
249 T_VIRTUAL_CALL();
250 return writeMessageBegin_virt(name, messageType, seqid);
251 }
252
253 uint32_t writeMessageEnd() {
254 T_VIRTUAL_CALL();
255 return writeMessageEnd_virt();
256 }
257
David Reiss6806fb82010-10-06 17:09:52 +0000258 uint32_t writeStructBegin(const char* name) {
259 T_VIRTUAL_CALL();
260 return writeStructBegin_virt(name);
261 }
262
263 uint32_t writeStructEnd() {
264 T_VIRTUAL_CALL();
265 return writeStructEnd_virt();
266 }
267
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100268 uint32_t writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId) {
David Reiss6806fb82010-10-06 17:09:52 +0000269 T_VIRTUAL_CALL();
270 return writeFieldBegin_virt(name, fieldType, fieldId);
271 }
272
273 uint32_t writeFieldEnd() {
274 T_VIRTUAL_CALL();
275 return writeFieldEnd_virt();
276 }
277
278 uint32_t writeFieldStop() {
279 T_VIRTUAL_CALL();
280 return writeFieldStop_virt();
281 }
282
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100283 uint32_t writeMapBegin(const TType keyType, const TType valType, const uint32_t size) {
David Reiss6806fb82010-10-06 17:09:52 +0000284 T_VIRTUAL_CALL();
285 return writeMapBegin_virt(keyType, valType, size);
286 }
287
288 uint32_t writeMapEnd() {
289 T_VIRTUAL_CALL();
290 return writeMapEnd_virt();
291 }
292
293 uint32_t writeListBegin(const TType elemType, const uint32_t size) {
294 T_VIRTUAL_CALL();
295 return writeListBegin_virt(elemType, size);
296 }
297
298 uint32_t writeListEnd() {
299 T_VIRTUAL_CALL();
300 return writeListEnd_virt();
301 }
302
303 uint32_t writeSetBegin(const TType elemType, const uint32_t size) {
304 T_VIRTUAL_CALL();
305 return writeSetBegin_virt(elemType, size);
306 }
307
308 uint32_t writeSetEnd() {
309 T_VIRTUAL_CALL();
310 return writeSetEnd_virt();
311 }
312
313 uint32_t writeBool(const bool value) {
314 T_VIRTUAL_CALL();
315 return writeBool_virt(value);
316 }
317
318 uint32_t writeByte(const int8_t byte) {
319 T_VIRTUAL_CALL();
320 return writeByte_virt(byte);
321 }
322
323 uint32_t writeI16(const int16_t i16) {
324 T_VIRTUAL_CALL();
325 return writeI16_virt(i16);
326 }
327
328 uint32_t writeI32(const int32_t i32) {
329 T_VIRTUAL_CALL();
330 return writeI32_virt(i32);
331 }
332
333 uint32_t writeI64(const int64_t i64) {
334 T_VIRTUAL_CALL();
335 return writeI64_virt(i64);
336 }
337
338 uint32_t writeDouble(const double dub) {
339 T_VIRTUAL_CALL();
340 return writeDouble_virt(dub);
341 }
342
343 uint32_t writeString(const std::string& str) {
344 T_VIRTUAL_CALL();
345 return writeString_virt(str);
346 }
347
348 uint32_t writeBinary(const std::string& str) {
349 T_VIRTUAL_CALL();
350 return writeBinary_virt(str);
351 }
David Reissc005b1b2008-02-15 01:38:18 +0000352
Mark Sleee8540632006-05-30 09:24:40 +0000353 /**
Mark Slee8d7e1f62006-06-07 06:48:56 +0000354 * Reading functions
Mark Sleee8540632006-05-30 09:24:40 +0000355 */
356
David Reiss6806fb82010-10-06 17:09:52 +0000357 virtual uint32_t readMessageBegin_virt(std::string& name,
358 TMessageType& messageType,
359 int32_t& seqid) = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000360
David Reiss6806fb82010-10-06 17:09:52 +0000361 virtual uint32_t readMessageEnd_virt() = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000362
David Reiss6806fb82010-10-06 17:09:52 +0000363 virtual uint32_t readStructBegin_virt(std::string& name) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000364
David Reiss6806fb82010-10-06 17:09:52 +0000365 virtual uint32_t readStructEnd_virt() = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000366
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100367 virtual uint32_t readFieldBegin_virt(std::string& name, TType& fieldType, int16_t& fieldId) = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000368
David Reiss6806fb82010-10-06 17:09:52 +0000369 virtual uint32_t readFieldEnd_virt() = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000370
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100371 virtual uint32_t readMapBegin_virt(TType& keyType, TType& valType, uint32_t& size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000372
David Reiss6806fb82010-10-06 17:09:52 +0000373 virtual uint32_t readMapEnd_virt() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000374
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100375 virtual uint32_t readListBegin_virt(TType& elemType, uint32_t& size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000376
David Reiss6806fb82010-10-06 17:09:52 +0000377 virtual uint32_t readListEnd_virt() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000378
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100379 virtual uint32_t readSetBegin_virt(TType& elemType, uint32_t& size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000380
David Reiss6806fb82010-10-06 17:09:52 +0000381 virtual uint32_t readSetEnd_virt() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000382
David Reiss6806fb82010-10-06 17:09:52 +0000383 virtual uint32_t readBool_virt(bool& value) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000384
David Reiss8dfc7322010-10-06 17:09:58 +0000385 virtual uint32_t readBool_virt(std::vector<bool>::reference value) = 0;
386
David Reiss6806fb82010-10-06 17:09:52 +0000387 virtual uint32_t readByte_virt(int8_t& byte) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000388
David Reiss6806fb82010-10-06 17:09:52 +0000389 virtual uint32_t readI16_virt(int16_t& i16) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000390
David Reiss6806fb82010-10-06 17:09:52 +0000391 virtual uint32_t readI32_virt(int32_t& i32) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000392
David Reiss6806fb82010-10-06 17:09:52 +0000393 virtual uint32_t readI64_virt(int64_t& i64) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000394
David Reiss6806fb82010-10-06 17:09:52 +0000395 virtual uint32_t readDouble_virt(double& dub) = 0;
Mark Sleec98d0502006-09-06 02:42:25 +0000396
David Reiss6806fb82010-10-06 17:09:52 +0000397 virtual uint32_t readString_virt(std::string& str) = 0;
Mark Sleee8540632006-05-30 09:24:40 +0000398
David Reiss6806fb82010-10-06 17:09:52 +0000399 virtual uint32_t readBinary_virt(std::string& str) = 0;
400
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100401 uint32_t readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid) {
David Reiss6806fb82010-10-06 17:09:52 +0000402 T_VIRTUAL_CALL();
403 return readMessageBegin_virt(name, messageType, seqid);
404 }
405
406 uint32_t readMessageEnd() {
407 T_VIRTUAL_CALL();
408 return readMessageEnd_virt();
409 }
410
411 uint32_t readStructBegin(std::string& name) {
412 T_VIRTUAL_CALL();
413 return readStructBegin_virt(name);
414 }
415
416 uint32_t readStructEnd() {
417 T_VIRTUAL_CALL();
418 return readStructEnd_virt();
419 }
420
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100421 uint32_t readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId) {
David Reiss6806fb82010-10-06 17:09:52 +0000422 T_VIRTUAL_CALL();
423 return readFieldBegin_virt(name, fieldType, fieldId);
424 }
425
426 uint32_t readFieldEnd() {
427 T_VIRTUAL_CALL();
428 return readFieldEnd_virt();
429 }
430
431 uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size) {
432 T_VIRTUAL_CALL();
433 return readMapBegin_virt(keyType, valType, size);
434 }
435
436 uint32_t readMapEnd() {
437 T_VIRTUAL_CALL();
438 return readMapEnd_virt();
439 }
440
441 uint32_t readListBegin(TType& elemType, uint32_t& size) {
442 T_VIRTUAL_CALL();
443 return readListBegin_virt(elemType, size);
444 }
445
446 uint32_t readListEnd() {
447 T_VIRTUAL_CALL();
448 return readListEnd_virt();
449 }
450
451 uint32_t readSetBegin(TType& elemType, uint32_t& size) {
452 T_VIRTUAL_CALL();
453 return readSetBegin_virt(elemType, size);
454 }
455
456 uint32_t readSetEnd() {
457 T_VIRTUAL_CALL();
458 return readSetEnd_virt();
459 }
460
461 uint32_t readBool(bool& value) {
462 T_VIRTUAL_CALL();
463 return readBool_virt(value);
464 }
465
466 uint32_t readByte(int8_t& byte) {
467 T_VIRTUAL_CALL();
468 return readByte_virt(byte);
469 }
470
471 uint32_t readI16(int16_t& i16) {
472 T_VIRTUAL_CALL();
473 return readI16_virt(i16);
474 }
475
476 uint32_t readI32(int32_t& i32) {
477 T_VIRTUAL_CALL();
478 return readI32_virt(i32);
479 }
480
481 uint32_t readI64(int64_t& i64) {
482 T_VIRTUAL_CALL();
483 return readI64_virt(i64);
484 }
485
486 uint32_t readDouble(double& dub) {
487 T_VIRTUAL_CALL();
488 return readDouble_virt(dub);
489 }
490
491 uint32_t readString(std::string& str) {
492 T_VIRTUAL_CALL();
493 return readString_virt(str);
494 }
495
496 uint32_t readBinary(std::string& str) {
497 T_VIRTUAL_CALL();
498 return readBinary_virt(str);
499 }
David Reissc005b1b2008-02-15 01:38:18 +0000500
David Reiss8dfc7322010-10-06 17:09:58 +0000501 /*
502 * std::vector is specialized for bool, and its elements are individual bits
503 * rather than bools. We need to define a different version of readBool()
504 * to work with std::vector<bool>.
505 */
506 uint32_t readBool(std::vector<bool>::reference value) {
507 T_VIRTUAL_CALL();
508 return readBool_virt(value);
David Reiss035aed92009-02-10 21:38:48 +0000509 }
510
Mark Sleee8540632006-05-30 09:24:40 +0000511 /**
Mark Slee8d7e1f62006-06-07 06:48:56 +0000512 * Method to arbitrarily skip over data.
Mark Sleee8540632006-05-30 09:24:40 +0000513 */
Mark Slee4af6ed72006-10-25 19:02:49 +0000514 uint32_t skip(TType type) {
David Reiss6806fb82010-10-06 17:09:52 +0000515 T_VIRTUAL_CALL();
516 return skip_virt(type);
517 }
Ben Craigcfaadcc2015-07-08 20:50:33 -0500518 virtual uint32_t skip_virt(TType type);
Mark Sleee8540632006-05-30 09:24:40 +0000519
cyy316723a2019-01-05 16:35:14 +0800520 inline std::shared_ptr<TTransport> getTransport() { return ptrans_; }
Mark Slee4af6ed72006-10-25 19:02:49 +0000521
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000522 // TODO: remove these two calls, they are for backwards
523 // compatibility
cyy316723a2019-01-05 16:35:14 +0800524 inline std::shared_ptr<TTransport> getInputTransport() { return ptrans_; }
525 inline std::shared_ptr<TTransport> getOutputTransport() { return ptrans_; }
Mark Slee4af6ed72006-10-25 19:02:49 +0000526
ben-craig02bade12015-07-17 08:40:48 -0500527 // input and output recursion depth are kept separate so that one protocol
528 // can be used concurrently for both input and output.
529 void incrementInputRecursionDepth() {
530 if (recursion_limit_ < ++input_recursion_depth_) {
Jens Geyer885c6792014-05-02 21:31:55 +0200531 throw TProtocolException(TProtocolException::DEPTH_LIMIT);
532 }
Mark Slee43b6c632007-02-07 00:54:17 +0000533 }
ben-craig02bade12015-07-17 08:40:48 -0500534 void decrementInputRecursionDepth() { --input_recursion_depth_; }
David Reiss0c90f6f2008-02-06 22:18:40 +0000535
ben-craig02bade12015-07-17 08:40:48 -0500536 void incrementOutputRecursionDepth() {
537 if (recursion_limit_ < ++output_recursion_depth_) {
538 throw TProtocolException(TProtocolException::DEPTH_LIMIT);
539 }
540 }
541 void decrementOutputRecursionDepth() { --output_recursion_depth_; }
542
Ben Craigcfaadcc2015-07-08 20:50:33 -0500543 uint32_t getRecursionLimit() const {return recursion_limit_;}
544 void setRecurisionLimit(uint32_t depth) {recursion_limit_ = depth;}
Jens Geyer885c6792014-05-02 21:31:55 +0200545
zeshuai00786352b42020-06-15 17:00:33 +0800546 // Returns the minimum amount of bytes needed to store the smallest possible instance of TType.
547 virtual int getMinSerializedSize(TType type) {
548 THRIFT_UNUSED_VARIABLE(type);
549 return 0;
550 }
551
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100552protected:
cyy316723a2019-01-05 16:35:14 +0800553 TProtocol(std::shared_ptr<TTransport> ptrans)
zeshuai00786352b42020-06-15 17:00:33 +0800554 : ptrans_(ptrans), input_recursion_depth_(0), output_recursion_depth_(0),
555 recursion_limit_(ptrans->getConfiguration()->getRecursionLimit())
Ben Craigcfaadcc2015-07-08 20:50:33 -0500556 {}
Jens Geyer885c6792014-05-02 21:31:55 +0200557
zeshuai00786352b42020-06-15 17:00:33 +0800558 virtual void checkReadBytesAvailable(TSet& set)
559 {
560 ptrans_->checkReadBytesAvailable(set.size_ * getMinSerializedSize(set.elemType_));
561 }
562
563 virtual void checkReadBytesAvailable(TList& list)
564 {
565 ptrans_->checkReadBytesAvailable(list.size_ * getMinSerializedSize(list.elemType_));
566 }
567
568 virtual void checkReadBytesAvailable(TMap& map)
569 {
570 int elmSize = getMinSerializedSize(map.keyType_) + getMinSerializedSize(map.valueType_);
571 ptrans_->checkReadBytesAvailable(map.size_ * elmSize);
572 }
573
cyy316723a2019-01-05 16:35:14 +0800574 std::shared_ptr<TTransport> ptrans_;
Mark Slee4af6ed72006-10-25 19:02:49 +0000575
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100576private:
Sebastian Zenker042580f2019-01-29 15:48:12 +0100577 TProtocol() = default;
ben-craig02bade12015-07-17 08:40:48 -0500578 uint32_t input_recursion_depth_;
579 uint32_t output_recursion_depth_;
Jens Geyer885c6792014-05-02 21:31:55 +0200580 uint32_t recursion_limit_;
Mark Sleee8540632006-05-30 09:24:40 +0000581};
582
Mark Slee4af6ed72006-10-25 19:02:49 +0000583/**
584 * Constructs input and output protocol objects given transports.
585 */
586class TProtocolFactory {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100587public:
Sebastian Zenker042580f2019-01-29 15:48:12 +0100588 TProtocolFactory() = default;
Mark Slee4af6ed72006-10-25 19:02:49 +0000589
Ben Craigcfaadcc2015-07-08 20:50:33 -0500590 virtual ~TProtocolFactory();
Mark Slee4af6ed72006-10-25 19:02:49 +0000591
cyy316723a2019-01-05 16:35:14 +0800592 virtual std::shared_ptr<TProtocol> getProtocol(std::shared_ptr<TTransport> trans) = 0;
593 virtual std::shared_ptr<TProtocol> getProtocol(std::shared_ptr<TTransport> inTrans,
594 std::shared_ptr<TTransport> outTrans) {
Dave Watson792db4e2015-01-16 11:22:01 -0800595 (void)outTrans;
596 return getProtocol(inTrans);
597 }
Mark Slee4af6ed72006-10-25 19:02:49 +0000598};
599
David Reissb7762a02010-10-06 17:10:00 +0000600/**
601 * Dummy protocol class.
602 *
603 * This class does nothing, and should never be instantiated.
604 * It is used only by the generator code.
605 */
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100606class TDummyProtocol : public TProtocol {};
Ben Craig384f9762015-07-08 20:33:03 -0500607
608// This is the default / legacy choice
609struct TNetworkBigEndian
610{
611 static uint16_t toWire16(uint16_t x) {return htons(x);}
612 static uint32_t toWire32(uint32_t x) {return htonl(x);}
jfarrellad3a9552015-09-24 23:27:34 -0400613 static uint64_t toWire64(uint64_t x) {return THRIFT_htonll(x);}
Ben Craig384f9762015-07-08 20:33:03 -0500614 static uint16_t fromWire16(uint16_t x) {return ntohs(x);}
615 static uint32_t fromWire32(uint32_t x) {return ntohl(x);}
jfarrellad3a9552015-09-24 23:27:34 -0400616 static uint64_t fromWire64(uint64_t x) {return THRIFT_ntohll(x);}
Ben Craig384f9762015-07-08 20:33:03 -0500617};
618
619// On most systems, this will be a bit faster than TNetworkBigEndian
620struct TNetworkLittleEndian
621{
622 static uint16_t toWire16(uint16_t x) {return THRIFT_htoles(x);}
623 static uint32_t toWire32(uint32_t x) {return THRIFT_htolel(x);}
jfarrellad3a9552015-09-24 23:27:34 -0400624 static uint64_t toWire64(uint64_t x) {return THRIFT_htolell(x);}
Ben Craig384f9762015-07-08 20:33:03 -0500625 static uint16_t fromWire16(uint16_t x) {return THRIFT_letohs(x);}
626 static uint32_t fromWire32(uint32_t x) {return THRIFT_letohl(x);}
jfarrellad3a9552015-09-24 23:27:34 -0400627 static uint64_t fromWire64(uint64_t x) {return THRIFT_letohll(x);}
Ben Craig384f9762015-07-08 20:33:03 -0500628};
629
ben-craig02bade12015-07-17 08:40:48 -0500630struct TOutputRecursionTracker {
Ben Craigcfaadcc2015-07-08 20:50:33 -0500631 TProtocol &prot_;
ben-craig02bade12015-07-17 08:40:48 -0500632 TOutputRecursionTracker(TProtocol &prot) : prot_(prot) {
633 prot_.incrementOutputRecursionDepth();
Ben Craigcfaadcc2015-07-08 20:50:33 -0500634 }
ben-craig02bade12015-07-17 08:40:48 -0500635 ~TOutputRecursionTracker() {
636 prot_.decrementOutputRecursionDepth();
637 }
638};
639
640struct TInputRecursionTracker {
641 TProtocol &prot_;
642 TInputRecursionTracker(TProtocol &prot) : prot_(prot) {
643 prot_.incrementInputRecursionDepth();
644 }
645 ~TInputRecursionTracker() {
646 prot_.decrementInputRecursionDepth();
Ben Craigcfaadcc2015-07-08 20:50:33 -0500647 }
648};
649
650/**
651 * Helper template for implementing TProtocol::skip().
652 *
653 * Templatized to avoid having to make virtual function calls.
654 */
655template <class Protocol_>
656uint32_t skip(Protocol_& prot, TType type) {
ben-craig02bade12015-07-17 08:40:48 -0500657 TInputRecursionTracker tracker(prot);
Ben Craigcfaadcc2015-07-08 20:50:33 -0500658
659 switch (type) {
660 case T_BOOL: {
661 bool boolv;
662 return prot.readBool(boolv);
663 }
664 case T_BYTE: {
James E. King, III07f59972017-03-10 06:18:33 -0500665 int8_t bytev = 0;
Ben Craigcfaadcc2015-07-08 20:50:33 -0500666 return prot.readByte(bytev);
667 }
668 case T_I16: {
669 int16_t i16;
670 return prot.readI16(i16);
671 }
672 case T_I32: {
673 int32_t i32;
674 return prot.readI32(i32);
675 }
676 case T_I64: {
677 int64_t i64;
678 return prot.readI64(i64);
679 }
680 case T_DOUBLE: {
681 double dub;
682 return prot.readDouble(dub);
683 }
684 case T_STRING: {
685 std::string str;
686 return prot.readBinary(str);
687 }
688 case T_STRUCT: {
689 uint32_t result = 0;
690 std::string name;
691 int16_t fid;
692 TType ftype;
693 result += prot.readStructBegin(name);
694 while (true) {
695 result += prot.readFieldBegin(name, ftype, fid);
696 if (ftype == T_STOP) {
697 break;
698 }
699 result += skip(prot, ftype);
700 result += prot.readFieldEnd();
701 }
702 result += prot.readStructEnd();
703 return result;
704 }
705 case T_MAP: {
706 uint32_t result = 0;
707 TType keyType;
708 TType valType;
709 uint32_t i, size;
710 result += prot.readMapBegin(keyType, valType, size);
711 for (i = 0; i < size; i++) {
712 result += skip(prot, keyType);
713 result += skip(prot, valType);
714 }
715 result += prot.readMapEnd();
716 return result;
717 }
718 case T_SET: {
719 uint32_t result = 0;
720 TType elemType;
721 uint32_t i, size;
722 result += prot.readSetBegin(elemType, size);
723 for (i = 0; i < size; i++) {
724 result += skip(prot, elemType);
725 }
726 result += prot.readSetEnd();
727 return result;
728 }
729 case T_LIST: {
730 uint32_t result = 0;
731 TType elemType;
732 uint32_t i, size;
733 result += prot.readListBegin(elemType, size);
734 for (i = 0; i < size; i++) {
735 result += skip(prot, elemType);
736 }
737 result += prot.readListEnd();
738 return result;
739 }
James E. King, III9ce1fd92017-09-23 21:20:08 -0700740 default:
James E. King IIIdbc1f8d2019-02-14 16:46:38 -0500741 break;
Ben Craigcfaadcc2015-07-08 20:50:33 -0500742 }
James E. King IIIdbc1f8d2019-02-14 16:46:38 -0500743
744 throw TProtocolException(TProtocolException::INVALID_DATA,
745 "invalid TType");
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100746}
Ben Craigcfaadcc2015-07-08 20:50:33 -0500747
748}}} // apache::thrift::protocol
Marc Slemko6f038a72006-08-03 18:58:09 +0000749
Mark Sleef5f2be42006-09-05 21:05:31 +0000750#endif // #define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1