blob: 846a32160ed879c2b07ac4de79059e7a4468454a [file] [log] [blame]
Mark Slee9f0c6512007-02-28 23:58:26 +00001// Copyright (c) 2006- Facebook
2// Distributed under the Thrift Software License
3//
4// See accompanying file LICENSE or visit the Thrift site at:
5// http://developers.facebook.com/thrift/
6
Mark Sleef5f2be42006-09-05 21:05:31 +00007#ifndef _THRIFT_PROTOCOL_TPROTOCOL_H_
8#define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1
Mark Sleee8540632006-05-30 09:24:40 +00009
Marc Slemko16698852006-08-04 03:16:10 +000010#include <transport/TTransport.h>
Mark Sleef9831082007-02-20 20:59:21 +000011#include <protocol/TProtocolException.h>
Marc Slemko16698852006-08-04 03:16:10 +000012
13#include <boost/shared_ptr.hpp>
14
Mark Slee8d7e1f62006-06-07 06:48:56 +000015#include <netinet/in.h>
Mark Sleee8540632006-05-30 09:24:40 +000016#include <sys/types.h>
17#include <string>
18#include <map>
19
Marc Slemko6f038a72006-08-03 18:58:09 +000020namespace facebook { namespace thrift { namespace protocol {
21
Marc Slemko16698852006-08-04 03:16:10 +000022using namespace boost;
23
Marc Slemko6f038a72006-08-03 18:58:09 +000024using namespace facebook::thrift::transport;
25
Mark Sleedc8a2a22006-09-19 22:20:18 +000026#if __BYTE_ORDER == __BIG_ENDIAN
27#define ntohll(n) (n)
28#define htonll(n) (n)
29#else
30#define ntohll(n) ( (((unsigned long long)ntohl(n)) << 32) + ntohl(n >> 32) )
31#define htonll(n) ( (((unsigned long long)htonl(n)) << 32) + htonl(n >> 32) )
32#endif
Mark Slee8d7e1f62006-06-07 06:48:56 +000033
Mark Sleee8540632006-05-30 09:24:40 +000034/**
Mark Slee8d7e1f62006-06-07 06:48:56 +000035 * Enumerated definition of the types that the Thrift protocol supports.
36 * Take special note of the T_END type which is used specifically to mark
37 * the end of a sequence of fields.
38 */
39enum TType {
Marc Slemkod42a2c22006-08-10 03:30:18 +000040 T_STOP = 0,
Marc Slemko5b126d62006-08-11 23:03:42 +000041 T_VOID = 1,
42 T_BOOL = 2,
43 T_BYTE = 3,
Mark Sleecfc01932006-09-01 22:18:16 +000044 T_I08 = 3,
Marc Slemko5b126d62006-08-11 23:03:42 +000045 T_I16 = 6,
Marc Slemko5b126d62006-08-11 23:03:42 +000046 T_I32 = 8,
47 T_U64 = 9,
48 T_I64 = 10,
Mark Sleec98d0502006-09-06 02:42:25 +000049 T_DOUBLE = 4,
Marc Slemko5b126d62006-08-11 23:03:42 +000050 T_STRING = 11,
Marc Slemkod97eb612006-08-24 23:37:36 +000051 T_UTF7 = 11,
52 T_STRUCT = 12,
53 T_MAP = 13,
54 T_SET = 14,
55 T_LIST = 15,
56 T_UTF8 = 16,
57 T_UTF16 = 17
Mark Slee8d7e1f62006-06-07 06:48:56 +000058};
59
60/**
Mark Sleef5f2be42006-09-05 21:05:31 +000061 * Enumerated definition of the message types that the Thrift protocol
62 * supports.
Marc Slemko16698852006-08-04 03:16:10 +000063 */
64enum TMessageType {
65 T_CALL = 1,
Mark Sleef9831082007-02-20 20:59:21 +000066 T_REPLY = 2,
67 T_EXCEPTION = 3
Marc Slemko16698852006-08-04 03:16:10 +000068};
69
70/**
Mark Sleee8540632006-05-30 09:24:40 +000071 * Abstract class for a thrift protocol driver. These are all the methods that
72 * a protocol must implement. Essentially, there must be some way of reading
73 * and writing all the base types, plus a mechanism for writing out structs
74 * with indexed fields. Also notice that all methods are strictly const. This
75 * is by design. Protcol impelementations may NOT keep state, because the
76 * same TProtocol object may be used simultaneously by multiple threads. This
77 * theoretically introduces some limititations into the possible protocol
78 * formats, but with the benefit of performance, clarity, and simplicity.
79 *
80 * @author Mark Slee <mcslee@facebook.com>
81 */
82class TProtocol {
83 public:
84 virtual ~TProtocol() {}
85
86 /**
Mark Slee8d7e1f62006-06-07 06:48:56 +000087 * Writing functions.
Mark Sleee8540632006-05-30 09:24:40 +000088 */
89
Mark Slee4af6ed72006-10-25 19:02:49 +000090 virtual uint32_t writeMessageBegin(const std::string name,
Marc Slemko0b4ffa92006-08-11 02:49:29 +000091 const TMessageType messageType,
Mark Slee4af6ed72006-10-25 19:02:49 +000092 const int32_t seqid) = 0;
Marc Slemko16698852006-08-04 03:16:10 +000093
Mark Slee4af6ed72006-10-25 19:02:49 +000094 virtual uint32_t writeMessageEnd() = 0;
Marc Slemko16698852006-08-04 03:16:10 +000095
96
Mark Slee4af6ed72006-10-25 19:02:49 +000097 virtual uint32_t writeStructBegin(const std::string& name) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +000098
Mark Slee4af6ed72006-10-25 19:02:49 +000099 virtual uint32_t writeStructEnd() = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000100
Mark Slee4af6ed72006-10-25 19:02:49 +0000101 virtual uint32_t writeFieldBegin(const std::string& name,
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000102 const TType fieldType,
Mark Slee4af6ed72006-10-25 19:02:49 +0000103 const int16_t fieldId) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000104
Mark Slee4af6ed72006-10-25 19:02:49 +0000105 virtual uint32_t writeFieldEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000106
Mark Slee4af6ed72006-10-25 19:02:49 +0000107 virtual uint32_t writeFieldStop() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000108
Mark Slee4af6ed72006-10-25 19:02:49 +0000109 virtual uint32_t writeMapBegin(const TType keyType,
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000110 const TType valType,
Mark Slee4af6ed72006-10-25 19:02:49 +0000111 const uint32_t size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000112
Mark Slee4af6ed72006-10-25 19:02:49 +0000113 virtual uint32_t writeMapEnd() = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000114
Mark Slee4af6ed72006-10-25 19:02:49 +0000115 virtual uint32_t writeListBegin(const TType elemType,
116 const uint32_t size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000117
Mark Slee4af6ed72006-10-25 19:02:49 +0000118 virtual uint32_t writeListEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000119
Mark Slee4af6ed72006-10-25 19:02:49 +0000120 virtual uint32_t writeSetBegin(const TType elemType,
121 const uint32_t size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000122
Mark Slee4af6ed72006-10-25 19:02:49 +0000123 virtual uint32_t writeSetEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000124
Mark Slee4af6ed72006-10-25 19:02:49 +0000125 virtual uint32_t writeBool(const bool value) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000126
Mark Slee4af6ed72006-10-25 19:02:49 +0000127 virtual uint32_t writeByte(const int8_t byte) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000128
Mark Slee4af6ed72006-10-25 19:02:49 +0000129 virtual uint32_t writeI16(const int16_t i16) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000130
Mark Slee4af6ed72006-10-25 19:02:49 +0000131 virtual uint32_t writeI32(const int32_t i32) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000132
Mark Slee4af6ed72006-10-25 19:02:49 +0000133 virtual uint32_t writeI64(const int64_t i64) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000134
Mark Slee4af6ed72006-10-25 19:02:49 +0000135 virtual uint32_t writeDouble(const double dub) = 0;
Mark Sleec98d0502006-09-06 02:42:25 +0000136
Mark Slee4af6ed72006-10-25 19:02:49 +0000137 virtual uint32_t writeString(const std::string& str) = 0;
Mark Sleee8540632006-05-30 09:24:40 +0000138
139 /**
Mark Slee8d7e1f62006-06-07 06:48:56 +0000140 * Reading functions
Mark Sleee8540632006-05-30 09:24:40 +0000141 */
142
Mark Slee4af6ed72006-10-25 19:02:49 +0000143 virtual uint32_t readMessageBegin(std::string& name,
Marc Slemko91f67482006-08-11 23:58:57 +0000144 TMessageType& messageType,
Mark Slee4af6ed72006-10-25 19:02:49 +0000145 int32_t& seqid) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000146
Mark Slee4af6ed72006-10-25 19:02:49 +0000147 virtual uint32_t readMessageEnd() = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000148
Mark Slee4af6ed72006-10-25 19:02:49 +0000149 virtual uint32_t readStructBegin(std::string& name) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000150
Mark Slee4af6ed72006-10-25 19:02:49 +0000151 virtual uint32_t readStructEnd() = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000152
Mark Slee4af6ed72006-10-25 19:02:49 +0000153 virtual uint32_t readFieldBegin(std::string& name,
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000154 TType& fieldType,
Mark Slee4af6ed72006-10-25 19:02:49 +0000155 int16_t& fieldId) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000156
Mark Slee4af6ed72006-10-25 19:02:49 +0000157 virtual uint32_t readFieldEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000158
Mark Slee4af6ed72006-10-25 19:02:49 +0000159 virtual uint32_t readMapBegin(TType& keyType,
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000160 TType& valType,
Mark Slee4af6ed72006-10-25 19:02:49 +0000161 uint32_t& size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000162
Mark Slee4af6ed72006-10-25 19:02:49 +0000163 virtual uint32_t readMapEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000164
Mark Slee4af6ed72006-10-25 19:02:49 +0000165 virtual uint32_t readListBegin(TType& elemType,
166 uint32_t& size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000167
Mark Slee4af6ed72006-10-25 19:02:49 +0000168 virtual uint32_t readListEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000169
Mark Slee4af6ed72006-10-25 19:02:49 +0000170 virtual uint32_t readSetBegin(TType& elemType,
171 uint32_t& size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000172
Mark Slee4af6ed72006-10-25 19:02:49 +0000173 virtual uint32_t readSetEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000174
Mark Slee4af6ed72006-10-25 19:02:49 +0000175 virtual uint32_t readBool(bool& value) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000176
Mark Slee4af6ed72006-10-25 19:02:49 +0000177 virtual uint32_t readByte(int8_t& byte) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000178
Mark Slee4af6ed72006-10-25 19:02:49 +0000179 virtual uint32_t readI16(int16_t& i16) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000180
Mark Slee4af6ed72006-10-25 19:02:49 +0000181 virtual uint32_t readI32(int32_t& i32) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000182
Mark Slee4af6ed72006-10-25 19:02:49 +0000183 virtual uint32_t readI64(int64_t& i64) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000184
Mark Slee4af6ed72006-10-25 19:02:49 +0000185 virtual uint32_t readDouble(double& dub) = 0;
Mark Sleec98d0502006-09-06 02:42:25 +0000186
Mark Slee4af6ed72006-10-25 19:02:49 +0000187 virtual uint32_t readString(std::string& str) = 0;
Mark Sleee8540632006-05-30 09:24:40 +0000188
189 /**
Mark Slee8d7e1f62006-06-07 06:48:56 +0000190 * Method to arbitrarily skip over data.
Mark Sleee8540632006-05-30 09:24:40 +0000191 */
Mark Slee4af6ed72006-10-25 19:02:49 +0000192 uint32_t skip(TType type) {
Mark Slee8d7e1f62006-06-07 06:48:56 +0000193 switch (type) {
Mark Slee78f58e22006-09-02 04:17:07 +0000194 case T_BOOL:
195 {
196 bool boolv;
Mark Slee4af6ed72006-10-25 19:02:49 +0000197 return readBool(boolv);
Mark Slee78f58e22006-09-02 04:17:07 +0000198 }
Mark Slee8d7e1f62006-06-07 06:48:56 +0000199 case T_BYTE:
200 {
Mark Slee78f58e22006-09-02 04:17:07 +0000201 int8_t bytev;
Mark Slee4af6ed72006-10-25 19:02:49 +0000202 return readByte(bytev);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000203 }
Mark Sleecfc01932006-09-01 22:18:16 +0000204 case T_I16:
Mark Slee8d7e1f62006-06-07 06:48:56 +0000205 {
Mark Sleecfc01932006-09-01 22:18:16 +0000206 int16_t i16;
Mark Slee4af6ed72006-10-25 19:02:49 +0000207 return readI16(i16);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000208 }
209 case T_I32:
210 {
211 int32_t i32;
Mark Slee4af6ed72006-10-25 19:02:49 +0000212 return readI32(i32);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000213 }
Mark Slee8d7e1f62006-06-07 06:48:56 +0000214 case T_I64:
215 {
216 int64_t i64;
Mark Slee4af6ed72006-10-25 19:02:49 +0000217 return readI64(i64);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000218 }
Mark Sleec98d0502006-09-06 02:42:25 +0000219 case T_DOUBLE:
220 {
221 double dub;
Mark Slee4af6ed72006-10-25 19:02:49 +0000222 return readDouble(dub);
Mark Sleec98d0502006-09-06 02:42:25 +0000223 }
Mark Slee8d7e1f62006-06-07 06:48:56 +0000224 case T_STRING:
225 {
226 std::string str;
Mark Slee4af6ed72006-10-25 19:02:49 +0000227 return readString(str);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000228 }
229 case T_STRUCT:
230 {
231 uint32_t result = 0;
232 std::string name;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000233 int16_t fid;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000234 TType ftype;
Mark Slee4af6ed72006-10-25 19:02:49 +0000235 result += readStructBegin(name);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000236 while (true) {
Mark Slee4af6ed72006-10-25 19:02:49 +0000237 result += readFieldBegin(name, ftype, fid);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000238 if (ftype == T_STOP) {
239 break;
240 }
Mark Slee4af6ed72006-10-25 19:02:49 +0000241 result += skip(ftype);
242 result += readFieldEnd();
Mark Slee8d7e1f62006-06-07 06:48:56 +0000243 }
Mark Slee4af6ed72006-10-25 19:02:49 +0000244 result += readStructEnd();
Mark Slee8d7e1f62006-06-07 06:48:56 +0000245 return result;
246 }
247 case T_MAP:
248 {
249 uint32_t result = 0;
250 TType keyType;
251 TType valType;
Marc Slemkob09f5882006-08-23 22:03:34 +0000252 uint32_t i, size;
Mark Slee4af6ed72006-10-25 19:02:49 +0000253 result += readMapBegin(keyType, valType, size);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000254 for (i = 0; i < size; i++) {
Mark Slee4af6ed72006-10-25 19:02:49 +0000255 result += skip(keyType);
256 result += skip(valType);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000257 }
Mark Slee4af6ed72006-10-25 19:02:49 +0000258 result += readMapEnd();
Mark Slee8d7e1f62006-06-07 06:48:56 +0000259 return result;
260 }
261 case T_SET:
262 {
263 uint32_t result = 0;
264 TType elemType;
Marc Slemkob09f5882006-08-23 22:03:34 +0000265 uint32_t i, size;
Mark Slee4af6ed72006-10-25 19:02:49 +0000266 result += readSetBegin(elemType, size);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000267 for (i = 0; i < size; i++) {
Mark Slee4af6ed72006-10-25 19:02:49 +0000268 result += skip(elemType);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000269 }
Mark Slee4af6ed72006-10-25 19:02:49 +0000270 result += readSetEnd();
Mark Slee8d7e1f62006-06-07 06:48:56 +0000271 return result;
272 }
273 case T_LIST:
274 {
275 uint32_t result = 0;
276 TType elemType;
Marc Slemkob09f5882006-08-23 22:03:34 +0000277 uint32_t i, size;
Mark Slee4af6ed72006-10-25 19:02:49 +0000278 result += readListBegin(elemType, size);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000279 for (i = 0; i < size; i++) {
Mark Slee4af6ed72006-10-25 19:02:49 +0000280 result += skip(elemType);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000281 }
Mark Slee4af6ed72006-10-25 19:02:49 +0000282 result += readListEnd();
Mark Slee8d7e1f62006-06-07 06:48:56 +0000283 return result;
284 }
285 default:
286 return 0;
287 }
288 }
Mark Sleee8540632006-05-30 09:24:40 +0000289
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000290 inline shared_ptr<TTransport> getTransport() {
Mark Slee43b6c632007-02-07 00:54:17 +0000291 return ptrans_;
Mark Slee4af6ed72006-10-25 19:02:49 +0000292 }
293
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000294 // TODO: remove these two calls, they are for backwards
295 // compatibility
296 inline shared_ptr<TTransport> getInputTransport() {
Mark Slee43b6c632007-02-07 00:54:17 +0000297 return ptrans_;
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000298 }
299 inline shared_ptr<TTransport> getOutputTransport() {
Mark Slee43b6c632007-02-07 00:54:17 +0000300 return ptrans_;
Mark Slee4af6ed72006-10-25 19:02:49 +0000301 }
302
Mark Sleee8540632006-05-30 09:24:40 +0000303 protected:
Mark Slee43b6c632007-02-07 00:54:17 +0000304 TProtocol(shared_ptr<TTransport> ptrans):
305 ptrans_(ptrans) {
306 trans_ = ptrans.get();
307 }
Mark Slee4af6ed72006-10-25 19:02:49 +0000308
Mark Slee43b6c632007-02-07 00:54:17 +0000309 shared_ptr<TTransport> ptrans_;
310 TTransport* trans_;
Mark Slee4af6ed72006-10-25 19:02:49 +0000311
312 private:
Mark Sleee8540632006-05-30 09:24:40 +0000313 TProtocol() {}
314};
315
Mark Slee4af6ed72006-10-25 19:02:49 +0000316/**
317 * Constructs input and output protocol objects given transports.
318 */
319class TProtocolFactory {
320 public:
321 TProtocolFactory() {}
322
323 virtual ~TProtocolFactory() {}
324
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000325 virtual boost::shared_ptr<TProtocol> getProtocol(boost::shared_ptr<TTransport> trans) = 0;
Mark Slee4af6ed72006-10-25 19:02:49 +0000326};
327
Marc Slemko6f038a72006-08-03 18:58:09 +0000328}}} // facebook::thrift::protocol
329
Mark Sleef5f2be42006-09-05 21:05:31 +0000330#endif // #define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1