blob: 63b959163d48cfa90c9e7df284a3311466d637b8 [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
Mario Emmenlauer49c6ec72023-10-10 10:46:09 +020024// Including Winsock2.h adds problematic macros like min() and max().
25// Try to work around:
26#ifndef NOMINMAX
27#define NOMINMAX
28#define _THRIFT_UNDEF_NOMINMAX
29#endif
30#ifndef WIN32_LEAN_AND_MEAN
31#define WIN32_LEAN_AND_MEAN
32#define _THRIFT_UNDEF_WIN32_LEAN_AND_MEAN
33#endif
Nobuaki Sukegawa11da87e2016-09-10 14:02:19 +090034// Need to come before any Windows.h includes
Jeremiah50819ce2022-02-08 12:46:45 +010035#include <winsock2.h>
Mario Emmenlauer49c6ec72023-10-10 10:46:09 +020036#ifdef _THRIFT_UNDEF_NOMINMAX
37#undef NOMINMAX
38#undef _THRIFT_UNDEF_NOMINMAX
39#endif
40#ifdef _THRIFT_UNDEF_WIN32_LEAN_AND_MEAN
41#undef WIN32_LEAN_AND_MEAN
42#undef _THRIFT_UNDEF_WIN32_LEAN_AND_MEAN
43#endif
Nobuaki Sukegawa11da87e2016-09-10 14:02:19 +090044#endif
45
Roger Meier49ff8b12012-04-13 09:12:31 +000046#include <thrift/transport/TTransport.h>
47#include <thrift/protocol/TProtocolException.h>
zeshuai00786352b42020-06-15 17:00:33 +080048#include <thrift/protocol/TEnum.h>
49#include <thrift/protocol/TList.h>
50#include <thrift/protocol/TSet.h>
51#include <thrift/protocol/TMap.h>
CJCombrink4b909092024-04-27 19:51:39 +020052#include <thrift/TUuid.h>
Marc Slemko16698852006-08-04 03:16:10 +000053
cyy316723a2019-01-05 16:35:14 +080054#include <memory>
Marc Slemko16698852006-08-04 03:16:10 +000055
Roger Meier2fa9c312011-09-05 19:15:53 +000056#ifdef HAVE_NETINET_IN_H
Mark Slee8d7e1f62006-06-07 06:48:56 +000057#include <netinet/in.h>
Roger Meier2fa9c312011-09-05 19:15:53 +000058#endif
Mark Sleee8540632006-05-30 09:24:40 +000059#include <sys/types.h>
60#include <string>
61#include <map>
David Reiss8dfc7322010-10-06 17:09:58 +000062#include <vector>
Ben Craigcfaadcc2015-07-08 20:50:33 -050063#include <climits>
Mark Sleee8540632006-05-30 09:24:40 +000064
David Reisse4d4ea02009-04-02 21:37:17 +000065// Use this to get around strict aliasing rules.
66// For example, uint64_t i = bitwise_cast<uint64_t>(returns_double());
67// The most obvious implementation is to just cast a pointer,
68// but that doesn't work.
69// For a pretty in-depth explanation of the problem, see
Jens Geyer1a8e0482015-04-30 20:29:20 +020070// http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html
David Reisse4d4ea02009-04-02 21:37:17 +000071template <typename To, typename From>
72static inline To bitwise_cast(From from) {
cyy863262d2019-01-06 10:40:58 +080073 static_assert(sizeof(From) == sizeof(To), "sizeof(From) == sizeof(To)");
David Reisse4d4ea02009-04-02 21:37:17 +000074
75 // BAD!!! These are all broken with -O2.
76 //return *reinterpret_cast<To*>(&from); // BAD!!!
77 //return *static_cast<To*>(static_cast<void*>(&from)); // BAD!!!
78 //return *(To*)(void*)&from; // BAD!!!
79
80 // Super clean and paritally blessed by section 3.9 of the standard.
81 //unsigned char c[sizeof(from)];
82 //memcpy(c, &from, sizeof(from));
83 //To to;
84 //memcpy(&to, c, sizeof(c));
85 //return to;
86
87 // Slightly more questionable.
88 // Same code emitted by GCC.
89 //To to;
90 //memcpy(&to, &from, sizeof(from));
91 //return to;
92
93 // Technically undefined, but almost universally supported,
94 // and the most efficient implementation.
95 union {
96 From f;
97 To t;
98 } u;
99 u.f = from;
100 return u.t;
101}
102
103
Jake Farrellc1fe30b2011-06-01 20:34:26 +0000104#ifdef HAVE_SYS_PARAM_H
Bryan Duxbury184d2622010-08-17 17:43:58 +0000105#include <sys/param.h>
Mark Slee4f261c52007-04-13 00:33:24 +0000106#endif
107
Chris Friedt0bc818f2022-09-26 16:02:50 -0400108#ifdef __ZEPHYR__
109# include <zephyr/sys/byteorder.h>
110
111# define __THRIFT_BYTE_ORDER __BYTE_ORDER__
112# define __THRIFT_LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
113# define __THRIFT_BIG_ENDIAN __ORDER_BIG_ENDIAN__
114
115# if __THRIFT_BYTE_ORDER == __THRIFT_BIG_ENDIAN
116# undef bswap_64
117# undef bswap_32
118# undef bswap_16
119# endif
120#endif
121
Roger Meierf9f841d2012-06-19 20:42:33 +0000122#ifndef __THRIFT_BYTE_ORDER
Mark Slee1d2ead32007-06-09 01:23:04 +0000123# if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
Roger Meierf9f841d2012-06-19 20:42:33 +0000124# define __THRIFT_BYTE_ORDER BYTE_ORDER
125# define __THRIFT_LITTLE_ENDIAN LITTLE_ENDIAN
126# define __THRIFT_BIG_ENDIAN BIG_ENDIAN
Mark Slee1d2ead32007-06-09 01:23:04 +0000127# else
James E. King IIIee8caca2019-05-04 08:20:59 -0400128# include <boost/predef/other/endian.h>
129# if BOOST_ENDIAN_BIG_BYTE
130# define __THRIFT_BYTE_ORDER 4321
131# define __THRIFT_LITTLE_ENDIAN 0
132# define __THRIFT_BIG_ENDIAN __THRIFT_BYTE_ORDER
133# elif BOOST_ENDIAN_LITTLE_BYTE
134# define __THRIFT_BYTE_ORDER 1234
135# define __THRIFT_LITTLE_ENDIAN __THRIFT_BYTE_ORDER
136# define __THRIFT_BIG_ENDIAN 0
137# endif
Roger Meiera93848b2011-09-12 22:20:11 +0000138# ifdef BOOST_LITTLE_ENDIAN
Roger Meiera93848b2011-09-12 22:20:11 +0000139# else
Roger Meiera93848b2011-09-12 22:20:11 +0000140# endif
Mark Slee1d2ead32007-06-09 01:23:04 +0000141# endif
142#endif
143
Roger Meierf9f841d2012-06-19 20:42:33 +0000144#if __THRIFT_BYTE_ORDER == __THRIFT_BIG_ENDIAN
jfarrellad3a9552015-09-24 23:27:34 -0400145# if !defined(THRIFT_ntohll)
146# define THRIFT_ntohll(n) (n)
147# define THRIFT_htonll(n) (n)
Jim King9dfe7b82015-05-06 09:51:54 -0400148# endif
David Reisse4d4ea02009-04-02 21:37:17 +0000149# if defined(__GNUC__) && defined(__GLIBC__)
150# include <byteswap.h>
jfarrellad3a9552015-09-24 23:27:34 -0400151# define THRIFT_htolell(n) bswap_64(n)
152# define THRIFT_letohll(n) bswap_64(n)
Ben Craig384f9762015-07-08 20:33:03 -0500153# define THRIFT_htolel(n) bswap_32(n)
154# define THRIFT_letohl(n) bswap_32(n)
155# define THRIFT_htoles(n) bswap_16(n)
156# define THRIFT_letohs(n) bswap_16(n)
David Reisse4d4ea02009-04-02 21:37:17 +0000157# else /* GNUC & GLIBC */
158# define bswap_64(n) \
159 ( (((n) & 0xff00000000000000ull) >> 56) \
160 | (((n) & 0x00ff000000000000ull) >> 40) \
161 | (((n) & 0x0000ff0000000000ull) >> 24) \
162 | (((n) & 0x000000ff00000000ull) >> 8) \
163 | (((n) & 0x00000000ff000000ull) << 8) \
164 | (((n) & 0x0000000000ff0000ull) << 24) \
165 | (((n) & 0x000000000000ff00ull) << 40) \
166 | (((n) & 0x00000000000000ffull) << 56) )
Ben Craig384f9762015-07-08 20:33:03 -0500167# define bswap_32(n) \
168 ( (((n) & 0xff000000ul) >> 24) \
169 | (((n) & 0x00ff0000ul) >> 8) \
170 | (((n) & 0x0000ff00ul) << 8) \
171 | (((n) & 0x000000fful) << 24) )
172# define bswap_16(n) \
Patrick Ganstererb7a1d8b2025-06-05 16:56:38 +0200173 ( (((n) & static_cast<unsigned short>(0xff00ul)) >> 8) \
174 | (((n) & static_cast<unsigned short>(0x00fful)) << 8) )
jfarrellad3a9552015-09-24 23:27:34 -0400175# define THRIFT_htolell(n) bswap_64(n)
176# define THRIFT_letohll(n) bswap_64(n)
Ben Craig384f9762015-07-08 20:33:03 -0500177# define THRIFT_htolel(n) bswap_32(n)
178# define THRIFT_letohl(n) bswap_32(n)
179# define THRIFT_htoles(n) bswap_16(n)
180# define THRIFT_letohs(n) bswap_16(n)
David Reisse4d4ea02009-04-02 21:37:17 +0000181# endif /* GNUC & GLIBC */
Roger Meierf9f841d2012-06-19 20:42:33 +0000182#elif __THRIFT_BYTE_ORDER == __THRIFT_LITTLE_ENDIAN
jfarrellad3a9552015-09-24 23:27:34 -0400183# define THRIFT_htolell(n) (n)
184# define THRIFT_letohll(n) (n)
Ben Craig384f9762015-07-08 20:33:03 -0500185# define THRIFT_htolel(n) (n)
186# define THRIFT_letohl(n) (n)
187# define THRIFT_htoles(n) (n)
188# define THRIFT_letohs(n) (n)
Mark Slee4f261c52007-04-13 00:33:24 +0000189# if defined(__GNUC__) && defined(__GLIBC__)
190# include <byteswap.h>
jfarrellad3a9552015-09-24 23:27:34 -0400191# define THRIFT_ntohll(n) bswap_64(n)
192# define THRIFT_htonll(n) bswap_64(n)
Roger Meierb69d24d2012-10-04 18:02:15 +0000193# elif defined(_MSC_VER) /* Microsoft Visual C++ */
Maximilian Bandle7c943352025-02-07 10:58:32 +0100194# define THRIFT_ntohll(n) ( _byteswap_uint64(static_cast<uint64_t>(n)) )
195# define THRIFT_htonll(n) ( _byteswap_uint64(static_cast<uint64_t>(n)) )
jfarrellad3a9552015-09-24 23:27:34 -0400196# elif !defined(THRIFT_ntohll) /* Not GNUC/GLIBC or MSVC */
Maximilian Bandle7c943352025-02-07 10:58:32 +0100197# define THRIFT_ntohll(n) ( (static_cast<uint64_t>(ntohl(static_cast<uint32_t>(n))) << 32) + ntohl(static_cast<uint32_t>(n >> 32)) )
198# define THRIFT_htonll(n) ( (static_cast<uint64_t>(htonl(static_cast<uint32_t>(n))) << 32) + htonl(static_cast<uint32_t>(n >> 32)) )
Roger Meierb69d24d2012-10-04 18:02:15 +0000199# endif /* GNUC/GLIBC or MSVC or something else */
Roger Meierf9f841d2012-06-19 20:42:33 +0000200#else /* __THRIFT_BYTE_ORDER */
jfarrellad3a9552015-09-24 23:27:34 -0400201# error "Can't define THRIFT_htonll or THRIFT_ntohll!"
Mark Sleedc8a2a22006-09-19 22:20:18 +0000202#endif
Mark Slee8d7e1f62006-06-07 06:48:56 +0000203
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100204namespace apache {
205namespace thrift {
206namespace protocol {
Ben Craigf4e6e622013-11-05 19:49:12 -0600207
208using apache::thrift::transport::TTransport;
209
Mark Sleee8540632006-05-30 09:24:40 +0000210/**
211 * Abstract class for a thrift protocol driver. These are all the methods that
212 * a protocol must implement. Essentially, there must be some way of reading
213 * and writing all the base types, plus a mechanism for writing out structs
Mark Slee5d06fea2007-03-05 22:18:18 +0000214 * with indexed fields.
215 *
216 * TProtocol objects should not be shared across multiple encoding contexts,
217 * as they may need to maintain internal state in some protocols (i.e. XML).
218 * Note that is is acceptable for the TProtocol module to do its own internal
219 * buffered reads/writes to the underlying TTransport where appropriate (i.e.
220 * when parsing an input XML stream, reading should be batched rather than
221 * looking ahead character by character for a close tag).
Mark Sleee8540632006-05-30 09:24:40 +0000222 *
Mark Sleee8540632006-05-30 09:24:40 +0000223 */
224class TProtocol {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100225public:
Ben Craigcfaadcc2015-07-08 20:50:33 -0500226 virtual ~TProtocol();
Mark Sleee8540632006-05-30 09:24:40 +0000227
228 /**
Mark Slee8d7e1f62006-06-07 06:48:56 +0000229 * Writing functions.
Mark Sleee8540632006-05-30 09:24:40 +0000230 */
231
David Reiss6806fb82010-10-06 17:09:52 +0000232 virtual uint32_t writeMessageBegin_virt(const std::string& name,
233 const TMessageType messageType,
234 const int32_t seqid) = 0;
Marc Slemko16698852006-08-04 03:16:10 +0000235
David Reiss6806fb82010-10-06 17:09:52 +0000236 virtual uint32_t writeMessageEnd_virt() = 0;
Marc Slemko16698852006-08-04 03:16:10 +0000237
David Reiss6806fb82010-10-06 17:09:52 +0000238 virtual uint32_t writeStructBegin_virt(const char* name) = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000239
David Reiss6806fb82010-10-06 17:09:52 +0000240 virtual uint32_t writeStructEnd_virt() = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000241
David Reiss6806fb82010-10-06 17:09:52 +0000242 virtual uint32_t writeFieldBegin_virt(const char* name,
243 const TType fieldType,
244 const int16_t fieldId) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000245
David Reiss6806fb82010-10-06 17:09:52 +0000246 virtual uint32_t writeFieldEnd_virt() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000247
David Reiss6806fb82010-10-06 17:09:52 +0000248 virtual uint32_t writeFieldStop_virt() = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000249
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100250 virtual uint32_t writeMapBegin_virt(const TType keyType, const TType valType, const uint32_t size)
251 = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000252
David Reiss6806fb82010-10-06 17:09:52 +0000253 virtual uint32_t writeMapEnd_virt() = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000254
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100255 virtual uint32_t writeListBegin_virt(const TType elemType, const uint32_t size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000256
David Reiss6806fb82010-10-06 17:09:52 +0000257 virtual uint32_t writeListEnd_virt() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000258
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100259 virtual uint32_t writeSetBegin_virt(const TType elemType, const uint32_t size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000260
David Reiss6806fb82010-10-06 17:09:52 +0000261 virtual uint32_t writeSetEnd_virt() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000262
David Reiss6806fb82010-10-06 17:09:52 +0000263 virtual uint32_t writeBool_virt(const bool value) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000264
David Reiss6806fb82010-10-06 17:09:52 +0000265 virtual uint32_t writeByte_virt(const int8_t byte) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000266
David Reiss6806fb82010-10-06 17:09:52 +0000267 virtual uint32_t writeI16_virt(const int16_t i16) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000268
David Reiss6806fb82010-10-06 17:09:52 +0000269 virtual uint32_t writeI32_virt(const int32_t i32) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000270
David Reiss6806fb82010-10-06 17:09:52 +0000271 virtual uint32_t writeI64_virt(const int64_t i64) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000272
David Reiss6806fb82010-10-06 17:09:52 +0000273 virtual uint32_t writeDouble_virt(const double dub) = 0;
Mark Sleec98d0502006-09-06 02:42:25 +0000274
David Reiss6806fb82010-10-06 17:09:52 +0000275 virtual uint32_t writeString_virt(const std::string& str) = 0;
Mark Sleee8540632006-05-30 09:24:40 +0000276
David Reiss6806fb82010-10-06 17:09:52 +0000277 virtual uint32_t writeBinary_virt(const std::string& str) = 0;
278
CJCombrink4b909092024-04-27 19:51:39 +0200279 virtual uint32_t writeUUID_virt(const TUuid& uuid) = 0;
CJCombrink1d886ca2024-03-23 21:32:28 +0100280
David Reiss6806fb82010-10-06 17:09:52 +0000281 uint32_t writeMessageBegin(const std::string& name,
282 const TMessageType messageType,
283 const int32_t seqid) {
284 T_VIRTUAL_CALL();
285 return writeMessageBegin_virt(name, messageType, seqid);
286 }
287
288 uint32_t writeMessageEnd() {
289 T_VIRTUAL_CALL();
290 return writeMessageEnd_virt();
291 }
292
David Reiss6806fb82010-10-06 17:09:52 +0000293 uint32_t writeStructBegin(const char* name) {
294 T_VIRTUAL_CALL();
295 return writeStructBegin_virt(name);
296 }
297
298 uint32_t writeStructEnd() {
299 T_VIRTUAL_CALL();
300 return writeStructEnd_virt();
301 }
302
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100303 uint32_t writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId) {
David Reiss6806fb82010-10-06 17:09:52 +0000304 T_VIRTUAL_CALL();
305 return writeFieldBegin_virt(name, fieldType, fieldId);
306 }
307
308 uint32_t writeFieldEnd() {
309 T_VIRTUAL_CALL();
310 return writeFieldEnd_virt();
311 }
312
313 uint32_t writeFieldStop() {
314 T_VIRTUAL_CALL();
315 return writeFieldStop_virt();
316 }
317
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100318 uint32_t writeMapBegin(const TType keyType, const TType valType, const uint32_t size) {
David Reiss6806fb82010-10-06 17:09:52 +0000319 T_VIRTUAL_CALL();
320 return writeMapBegin_virt(keyType, valType, size);
321 }
322
323 uint32_t writeMapEnd() {
324 T_VIRTUAL_CALL();
325 return writeMapEnd_virt();
326 }
327
328 uint32_t writeListBegin(const TType elemType, const uint32_t size) {
329 T_VIRTUAL_CALL();
330 return writeListBegin_virt(elemType, size);
331 }
332
333 uint32_t writeListEnd() {
334 T_VIRTUAL_CALL();
335 return writeListEnd_virt();
336 }
337
338 uint32_t writeSetBegin(const TType elemType, const uint32_t size) {
339 T_VIRTUAL_CALL();
340 return writeSetBegin_virt(elemType, size);
341 }
342
343 uint32_t writeSetEnd() {
344 T_VIRTUAL_CALL();
345 return writeSetEnd_virt();
346 }
347
348 uint32_t writeBool(const bool value) {
349 T_VIRTUAL_CALL();
350 return writeBool_virt(value);
351 }
352
353 uint32_t writeByte(const int8_t byte) {
354 T_VIRTUAL_CALL();
355 return writeByte_virt(byte);
356 }
357
358 uint32_t writeI16(const int16_t i16) {
359 T_VIRTUAL_CALL();
360 return writeI16_virt(i16);
361 }
362
363 uint32_t writeI32(const int32_t i32) {
364 T_VIRTUAL_CALL();
365 return writeI32_virt(i32);
366 }
367
368 uint32_t writeI64(const int64_t i64) {
369 T_VIRTUAL_CALL();
370 return writeI64_virt(i64);
371 }
372
373 uint32_t writeDouble(const double dub) {
374 T_VIRTUAL_CALL();
375 return writeDouble_virt(dub);
376 }
377
378 uint32_t writeString(const std::string& str) {
379 T_VIRTUAL_CALL();
380 return writeString_virt(str);
381 }
382
383 uint32_t writeBinary(const std::string& str) {
384 T_VIRTUAL_CALL();
385 return writeBinary_virt(str);
386 }
David Reissc005b1b2008-02-15 01:38:18 +0000387
CJCombrink4b909092024-04-27 19:51:39 +0200388 uint32_t writeUUID(const TUuid& uuid) {
CJCombrink1d886ca2024-03-23 21:32:28 +0100389 T_VIRTUAL_CALL();
CJCombrink4b909092024-04-27 19:51:39 +0200390 return writeUUID_virt(uuid);
CJCombrink1d886ca2024-03-23 21:32:28 +0100391 }
392
Mark Sleee8540632006-05-30 09:24:40 +0000393 /**
Mark Slee8d7e1f62006-06-07 06:48:56 +0000394 * Reading functions
Mark Sleee8540632006-05-30 09:24:40 +0000395 */
396
David Reiss6806fb82010-10-06 17:09:52 +0000397 virtual uint32_t readMessageBegin_virt(std::string& name,
398 TMessageType& messageType,
399 int32_t& seqid) = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000400
David Reiss6806fb82010-10-06 17:09:52 +0000401 virtual uint32_t readMessageEnd_virt() = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000402
David Reiss6806fb82010-10-06 17:09:52 +0000403 virtual uint32_t readStructBegin_virt(std::string& name) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000404
David Reiss6806fb82010-10-06 17:09:52 +0000405 virtual uint32_t readStructEnd_virt() = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000406
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100407 virtual uint32_t readFieldBegin_virt(std::string& name, TType& fieldType, int16_t& fieldId) = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000408
David Reiss6806fb82010-10-06 17:09:52 +0000409 virtual uint32_t readFieldEnd_virt() = 0;
David Reiss0c90f6f2008-02-06 22:18:40 +0000410
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100411 virtual uint32_t readMapBegin_virt(TType& keyType, TType& valType, uint32_t& size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000412
David Reiss6806fb82010-10-06 17:09:52 +0000413 virtual uint32_t readMapEnd_virt() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000414
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100415 virtual uint32_t readListBegin_virt(TType& elemType, uint32_t& size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000416
David Reiss6806fb82010-10-06 17:09:52 +0000417 virtual uint32_t readListEnd_virt() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000418
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100419 virtual uint32_t readSetBegin_virt(TType& elemType, uint32_t& size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000420
David Reiss6806fb82010-10-06 17:09:52 +0000421 virtual uint32_t readSetEnd_virt() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000422
David Reiss6806fb82010-10-06 17:09:52 +0000423 virtual uint32_t readBool_virt(bool& value) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000424
David Reiss8dfc7322010-10-06 17:09:58 +0000425 virtual uint32_t readBool_virt(std::vector<bool>::reference value) = 0;
426
David Reiss6806fb82010-10-06 17:09:52 +0000427 virtual uint32_t readByte_virt(int8_t& byte) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000428
David Reiss6806fb82010-10-06 17:09:52 +0000429 virtual uint32_t readI16_virt(int16_t& i16) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000430
David Reiss6806fb82010-10-06 17:09:52 +0000431 virtual uint32_t readI32_virt(int32_t& i32) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000432
David Reiss6806fb82010-10-06 17:09:52 +0000433 virtual uint32_t readI64_virt(int64_t& i64) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000434
David Reiss6806fb82010-10-06 17:09:52 +0000435 virtual uint32_t readDouble_virt(double& dub) = 0;
Mark Sleec98d0502006-09-06 02:42:25 +0000436
David Reiss6806fb82010-10-06 17:09:52 +0000437 virtual uint32_t readString_virt(std::string& str) = 0;
Mark Sleee8540632006-05-30 09:24:40 +0000438
David Reiss6806fb82010-10-06 17:09:52 +0000439 virtual uint32_t readBinary_virt(std::string& str) = 0;
440
CJCombrink4b909092024-04-27 19:51:39 +0200441 virtual uint32_t readUUID_virt(TUuid& uuid) = 0;
CJCombrink1d886ca2024-03-23 21:32:28 +0100442
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100443 uint32_t readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid) {
David Reiss6806fb82010-10-06 17:09:52 +0000444 T_VIRTUAL_CALL();
445 return readMessageBegin_virt(name, messageType, seqid);
446 }
447
448 uint32_t readMessageEnd() {
449 T_VIRTUAL_CALL();
450 return readMessageEnd_virt();
451 }
452
453 uint32_t readStructBegin(std::string& name) {
454 T_VIRTUAL_CALL();
455 return readStructBegin_virt(name);
456 }
457
458 uint32_t readStructEnd() {
459 T_VIRTUAL_CALL();
460 return readStructEnd_virt();
461 }
462
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100463 uint32_t readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId) {
David Reiss6806fb82010-10-06 17:09:52 +0000464 T_VIRTUAL_CALL();
465 return readFieldBegin_virt(name, fieldType, fieldId);
466 }
467
468 uint32_t readFieldEnd() {
469 T_VIRTUAL_CALL();
470 return readFieldEnd_virt();
471 }
472
473 uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size) {
474 T_VIRTUAL_CALL();
475 return readMapBegin_virt(keyType, valType, size);
476 }
477
478 uint32_t readMapEnd() {
479 T_VIRTUAL_CALL();
480 return readMapEnd_virt();
481 }
482
483 uint32_t readListBegin(TType& elemType, uint32_t& size) {
484 T_VIRTUAL_CALL();
485 return readListBegin_virt(elemType, size);
486 }
487
488 uint32_t readListEnd() {
489 T_VIRTUAL_CALL();
490 return readListEnd_virt();
491 }
492
493 uint32_t readSetBegin(TType& elemType, uint32_t& size) {
494 T_VIRTUAL_CALL();
495 return readSetBegin_virt(elemType, size);
496 }
497
498 uint32_t readSetEnd() {
499 T_VIRTUAL_CALL();
500 return readSetEnd_virt();
501 }
502
503 uint32_t readBool(bool& value) {
504 T_VIRTUAL_CALL();
505 return readBool_virt(value);
506 }
507
508 uint32_t readByte(int8_t& byte) {
509 T_VIRTUAL_CALL();
510 return readByte_virt(byte);
511 }
512
513 uint32_t readI16(int16_t& i16) {
514 T_VIRTUAL_CALL();
515 return readI16_virt(i16);
516 }
517
518 uint32_t readI32(int32_t& i32) {
519 T_VIRTUAL_CALL();
520 return readI32_virt(i32);
521 }
522
523 uint32_t readI64(int64_t& i64) {
524 T_VIRTUAL_CALL();
525 return readI64_virt(i64);
526 }
527
528 uint32_t readDouble(double& dub) {
529 T_VIRTUAL_CALL();
530 return readDouble_virt(dub);
531 }
532
533 uint32_t readString(std::string& str) {
534 T_VIRTUAL_CALL();
535 return readString_virt(str);
536 }
537
538 uint32_t readBinary(std::string& str) {
539 T_VIRTUAL_CALL();
540 return readBinary_virt(str);
541 }
David Reissc005b1b2008-02-15 01:38:18 +0000542
CJCombrink4b909092024-04-27 19:51:39 +0200543 uint32_t readUUID(TUuid& uuid) {
CJCombrink1d886ca2024-03-23 21:32:28 +0100544 T_VIRTUAL_CALL();
CJCombrink4b909092024-04-27 19:51:39 +0200545 return readUUID_virt(uuid);
CJCombrink1d886ca2024-03-23 21:32:28 +0100546 }
547
David Reiss8dfc7322010-10-06 17:09:58 +0000548 /*
549 * std::vector is specialized for bool, and its elements are individual bits
550 * rather than bools. We need to define a different version of readBool()
551 * to work with std::vector<bool>.
552 */
553 uint32_t readBool(std::vector<bool>::reference value) {
554 T_VIRTUAL_CALL();
555 return readBool_virt(value);
David Reiss035aed92009-02-10 21:38:48 +0000556 }
557
Mark Sleee8540632006-05-30 09:24:40 +0000558 /**
Mark Slee8d7e1f62006-06-07 06:48:56 +0000559 * Method to arbitrarily skip over data.
Mark Sleee8540632006-05-30 09:24:40 +0000560 */
Mark Slee4af6ed72006-10-25 19:02:49 +0000561 uint32_t skip(TType type) {
David Reiss6806fb82010-10-06 17:09:52 +0000562 T_VIRTUAL_CALL();
563 return skip_virt(type);
564 }
Ben Craigcfaadcc2015-07-08 20:50:33 -0500565 virtual uint32_t skip_virt(TType type);
Mark Sleee8540632006-05-30 09:24:40 +0000566
cyy316723a2019-01-05 16:35:14 +0800567 inline std::shared_ptr<TTransport> getTransport() { return ptrans_; }
Mark Slee4af6ed72006-10-25 19:02:49 +0000568
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000569 // TODO: remove these two calls, they are for backwards
570 // compatibility
cyy316723a2019-01-05 16:35:14 +0800571 inline std::shared_ptr<TTransport> getInputTransport() { return ptrans_; }
572 inline std::shared_ptr<TTransport> getOutputTransport() { return ptrans_; }
Mark Slee4af6ed72006-10-25 19:02:49 +0000573
ben-craig02bade12015-07-17 08:40:48 -0500574 // input and output recursion depth are kept separate so that one protocol
575 // can be used concurrently for both input and output.
576 void incrementInputRecursionDepth() {
577 if (recursion_limit_ < ++input_recursion_depth_) {
Jens Geyer885c6792014-05-02 21:31:55 +0200578 throw TProtocolException(TProtocolException::DEPTH_LIMIT);
579 }
Mark Slee43b6c632007-02-07 00:54:17 +0000580 }
ben-craig02bade12015-07-17 08:40:48 -0500581 void decrementInputRecursionDepth() { --input_recursion_depth_; }
David Reiss0c90f6f2008-02-06 22:18:40 +0000582
ben-craig02bade12015-07-17 08:40:48 -0500583 void incrementOutputRecursionDepth() {
584 if (recursion_limit_ < ++output_recursion_depth_) {
585 throw TProtocolException(TProtocolException::DEPTH_LIMIT);
586 }
587 }
588 void decrementOutputRecursionDepth() { --output_recursion_depth_; }
589
Ben Craigcfaadcc2015-07-08 20:50:33 -0500590 uint32_t getRecursionLimit() const {return recursion_limit_;}
591 void setRecurisionLimit(uint32_t depth) {recursion_limit_ = depth;}
Jens Geyer885c6792014-05-02 21:31:55 +0200592
zeshuai00786352b42020-06-15 17:00:33 +0800593 // Returns the minimum amount of bytes needed to store the smallest possible instance of TType.
Mario Emmenlauer49c6ec72023-10-10 10:46:09 +0200594 virtual int getMinSerializedSize(TType type) {
zeshuai00786352b42020-06-15 17:00:33 +0800595 THRIFT_UNUSED_VARIABLE(type);
596 return 0;
597 }
598
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100599protected:
cyy316723a2019-01-05 16:35:14 +0800600 TProtocol(std::shared_ptr<TTransport> ptrans)
Mario Emmenlauer49c6ec72023-10-10 10:46:09 +0200601 : ptrans_(ptrans), input_recursion_depth_(0), output_recursion_depth_(0),
zeshuai00786352b42020-06-15 17:00:33 +0800602 recursion_limit_(ptrans->getConfiguration()->getRecursionLimit())
Ben Craigcfaadcc2015-07-08 20:50:33 -0500603 {}
Jens Geyer885c6792014-05-02 21:31:55 +0200604
zeshuai00786352b42020-06-15 17:00:33 +0800605 virtual void checkReadBytesAvailable(TSet& set)
606 {
607 ptrans_->checkReadBytesAvailable(set.size_ * getMinSerializedSize(set.elemType_));
608 }
609
610 virtual void checkReadBytesAvailable(TList& list)
611 {
612 ptrans_->checkReadBytesAvailable(list.size_ * getMinSerializedSize(list.elemType_));
613 }
614
615 virtual void checkReadBytesAvailable(TMap& map)
616 {
617 int elmSize = getMinSerializedSize(map.keyType_) + getMinSerializedSize(map.valueType_);
618 ptrans_->checkReadBytesAvailable(map.size_ * elmSize);
619 }
620
cyy316723a2019-01-05 16:35:14 +0800621 std::shared_ptr<TTransport> ptrans_;
Mark Slee4af6ed72006-10-25 19:02:49 +0000622
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100623private:
Sebastian Zenker042580f2019-01-29 15:48:12 +0100624 TProtocol() = default;
ben-craig02bade12015-07-17 08:40:48 -0500625 uint32_t input_recursion_depth_;
626 uint32_t output_recursion_depth_;
Jens Geyer885c6792014-05-02 21:31:55 +0200627 uint32_t recursion_limit_;
Mark Sleee8540632006-05-30 09:24:40 +0000628};
629
Mark Slee4af6ed72006-10-25 19:02:49 +0000630/**
631 * Constructs input and output protocol objects given transports.
632 */
633class TProtocolFactory {
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100634public:
Sebastian Zenker042580f2019-01-29 15:48:12 +0100635 TProtocolFactory() = default;
Mark Slee4af6ed72006-10-25 19:02:49 +0000636
Ben Craigcfaadcc2015-07-08 20:50:33 -0500637 virtual ~TProtocolFactory();
Mark Slee4af6ed72006-10-25 19:02:49 +0000638
cyy316723a2019-01-05 16:35:14 +0800639 virtual std::shared_ptr<TProtocol> getProtocol(std::shared_ptr<TTransport> trans) = 0;
640 virtual std::shared_ptr<TProtocol> getProtocol(std::shared_ptr<TTransport> inTrans,
641 std::shared_ptr<TTransport> outTrans) {
Dave Watson792db4e2015-01-16 11:22:01 -0800642 (void)outTrans;
643 return getProtocol(inTrans);
644 }
Mark Slee4af6ed72006-10-25 19:02:49 +0000645};
646
David Reissb7762a02010-10-06 17:10:00 +0000647/**
648 * Dummy protocol class.
649 *
650 * This class does nothing, and should never be instantiated.
651 * It is used only by the generator code.
652 */
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100653class TDummyProtocol : public TProtocol {};
Ben Craig384f9762015-07-08 20:33:03 -0500654
655// This is the default / legacy choice
656struct TNetworkBigEndian
657{
658 static uint16_t toWire16(uint16_t x) {return htons(x);}
659 static uint32_t toWire32(uint32_t x) {return htonl(x);}
jfarrellad3a9552015-09-24 23:27:34 -0400660 static uint64_t toWire64(uint64_t x) {return THRIFT_htonll(x);}
Ben Craig384f9762015-07-08 20:33:03 -0500661 static uint16_t fromWire16(uint16_t x) {return ntohs(x);}
662 static uint32_t fromWire32(uint32_t x) {return ntohl(x);}
jfarrellad3a9552015-09-24 23:27:34 -0400663 static uint64_t fromWire64(uint64_t x) {return THRIFT_ntohll(x);}
Ben Craig384f9762015-07-08 20:33:03 -0500664};
665
666// On most systems, this will be a bit faster than TNetworkBigEndian
667struct TNetworkLittleEndian
668{
669 static uint16_t toWire16(uint16_t x) {return THRIFT_htoles(x);}
670 static uint32_t toWire32(uint32_t x) {return THRIFT_htolel(x);}
jfarrellad3a9552015-09-24 23:27:34 -0400671 static uint64_t toWire64(uint64_t x) {return THRIFT_htolell(x);}
Ben Craig384f9762015-07-08 20:33:03 -0500672 static uint16_t fromWire16(uint16_t x) {return THRIFT_letohs(x);}
673 static uint32_t fromWire32(uint32_t x) {return THRIFT_letohl(x);}
jfarrellad3a9552015-09-24 23:27:34 -0400674 static uint64_t fromWire64(uint64_t x) {return THRIFT_letohll(x);}
Ben Craig384f9762015-07-08 20:33:03 -0500675};
676
ben-craig02bade12015-07-17 08:40:48 -0500677struct TOutputRecursionTracker {
Ben Craigcfaadcc2015-07-08 20:50:33 -0500678 TProtocol &prot_;
ben-craig02bade12015-07-17 08:40:48 -0500679 TOutputRecursionTracker(TProtocol &prot) : prot_(prot) {
680 prot_.incrementOutputRecursionDepth();
Ben Craigcfaadcc2015-07-08 20:50:33 -0500681 }
ben-craig02bade12015-07-17 08:40:48 -0500682 ~TOutputRecursionTracker() {
683 prot_.decrementOutputRecursionDepth();
684 }
685};
686
687struct TInputRecursionTracker {
688 TProtocol &prot_;
689 TInputRecursionTracker(TProtocol &prot) : prot_(prot) {
690 prot_.incrementInputRecursionDepth();
691 }
692 ~TInputRecursionTracker() {
693 prot_.decrementInputRecursionDepth();
Ben Craigcfaadcc2015-07-08 20:50:33 -0500694 }
695};
696
697/**
698 * Helper template for implementing TProtocol::skip().
699 *
700 * Templatized to avoid having to make virtual function calls.
701 */
702template <class Protocol_>
703uint32_t skip(Protocol_& prot, TType type) {
ben-craig02bade12015-07-17 08:40:48 -0500704 TInputRecursionTracker tracker(prot);
Ben Craigcfaadcc2015-07-08 20:50:33 -0500705
706 switch (type) {
707 case T_BOOL: {
708 bool boolv;
709 return prot.readBool(boolv);
710 }
711 case T_BYTE: {
James E. King, III07f59972017-03-10 06:18:33 -0500712 int8_t bytev = 0;
Ben Craigcfaadcc2015-07-08 20:50:33 -0500713 return prot.readByte(bytev);
714 }
715 case T_I16: {
716 int16_t i16;
717 return prot.readI16(i16);
718 }
719 case T_I32: {
720 int32_t i32;
721 return prot.readI32(i32);
722 }
723 case T_I64: {
724 int64_t i64;
725 return prot.readI64(i64);
726 }
727 case T_DOUBLE: {
728 double dub;
729 return prot.readDouble(dub);
730 }
731 case T_STRING: {
732 std::string str;
733 return prot.readBinary(str);
734 }
735 case T_STRUCT: {
736 uint32_t result = 0;
737 std::string name;
738 int16_t fid;
739 TType ftype;
740 result += prot.readStructBegin(name);
741 while (true) {
742 result += prot.readFieldBegin(name, ftype, fid);
743 if (ftype == T_STOP) {
744 break;
745 }
746 result += skip(prot, ftype);
747 result += prot.readFieldEnd();
748 }
749 result += prot.readStructEnd();
750 return result;
751 }
752 case T_MAP: {
753 uint32_t result = 0;
754 TType keyType;
755 TType valType;
756 uint32_t i, size;
757 result += prot.readMapBegin(keyType, valType, size);
758 for (i = 0; i < size; i++) {
759 result += skip(prot, keyType);
760 result += skip(prot, valType);
761 }
762 result += prot.readMapEnd();
763 return result;
764 }
765 case T_SET: {
766 uint32_t result = 0;
767 TType elemType;
768 uint32_t i, size;
769 result += prot.readSetBegin(elemType, size);
770 for (i = 0; i < size; i++) {
771 result += skip(prot, elemType);
772 }
773 result += prot.readSetEnd();
774 return result;
775 }
776 case T_LIST: {
777 uint32_t result = 0;
778 TType elemType;
779 uint32_t i, size;
780 result += prot.readListBegin(elemType, size);
781 for (i = 0; i < size; i++) {
782 result += skip(prot, elemType);
783 }
784 result += prot.readListEnd();
785 return result;
786 }
James E. King, III9ce1fd92017-09-23 21:20:08 -0700787 default:
James E. King IIIdbc1f8d2019-02-14 16:46:38 -0500788 break;
Ben Craigcfaadcc2015-07-08 20:50:33 -0500789 }
James E. King IIIdbc1f8d2019-02-14 16:46:38 -0500790
791 throw TProtocolException(TProtocolException::INVALID_DATA,
792 "invalid TType");
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100793}
Ben Craigcfaadcc2015-07-08 20:50:33 -0500794
795}}} // apache::thrift::protocol
Marc Slemko6f038a72006-08-03 18:58:09 +0000796
Mark Sleef5f2be42006-09-05 21:05:31 +0000797#endif // #define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1