blob: 42bea2b691dc5786a1c7c201b348467bddee0e7e [file] [log] [blame]
Mark Sleef5f2be42006-09-05 21:05:31 +00001#ifndef _THRIFT_PROTOCOL_TPROTOCOL_H_
2#define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1
Mark Sleee8540632006-05-30 09:24:40 +00003
Marc Slemko16698852006-08-04 03:16:10 +00004#include <transport/TTransport.h>
Mark Sleef9831082007-02-20 20:59:21 +00005#include <protocol/TProtocolException.h>
Marc Slemko16698852006-08-04 03:16:10 +00006
7#include <boost/shared_ptr.hpp>
8
Mark Slee8d7e1f62006-06-07 06:48:56 +00009#include <netinet/in.h>
Mark Sleee8540632006-05-30 09:24:40 +000010#include <sys/types.h>
11#include <string>
12#include <map>
13
Marc Slemko6f038a72006-08-03 18:58:09 +000014namespace facebook { namespace thrift { namespace protocol {
15
Marc Slemko16698852006-08-04 03:16:10 +000016using namespace boost;
17
Marc Slemko6f038a72006-08-03 18:58:09 +000018using namespace facebook::thrift::transport;
19
Mark Sleedc8a2a22006-09-19 22:20:18 +000020#if __BYTE_ORDER == __BIG_ENDIAN
21#define ntohll(n) (n)
22#define htonll(n) (n)
23#else
24#define ntohll(n) ( (((unsigned long long)ntohl(n)) << 32) + ntohl(n >> 32) )
25#define htonll(n) ( (((unsigned long long)htonl(n)) << 32) + htonl(n >> 32) )
26#endif
Mark Slee8d7e1f62006-06-07 06:48:56 +000027
Mark Sleef5f2be42006-09-05 21:05:31 +000028// Forward declaration for TProtocol
Mark Sleee8540632006-05-30 09:24:40 +000029struct TBuf;
30
31/**
Mark Slee8d7e1f62006-06-07 06:48:56 +000032 * Enumerated definition of the types that the Thrift protocol supports.
33 * Take special note of the T_END type which is used specifically to mark
34 * the end of a sequence of fields.
35 */
36enum TType {
Marc Slemkod42a2c22006-08-10 03:30:18 +000037 T_STOP = 0,
Marc Slemko5b126d62006-08-11 23:03:42 +000038 T_VOID = 1,
39 T_BOOL = 2,
40 T_BYTE = 3,
Mark Sleecfc01932006-09-01 22:18:16 +000041 T_I08 = 3,
Marc Slemko5b126d62006-08-11 23:03:42 +000042 T_I16 = 6,
Marc Slemko5b126d62006-08-11 23:03:42 +000043 T_I32 = 8,
44 T_U64 = 9,
45 T_I64 = 10,
Mark Sleec98d0502006-09-06 02:42:25 +000046 T_DOUBLE = 4,
Marc Slemko5b126d62006-08-11 23:03:42 +000047 T_STRING = 11,
Marc Slemkod97eb612006-08-24 23:37:36 +000048 T_UTF7 = 11,
49 T_STRUCT = 12,
50 T_MAP = 13,
51 T_SET = 14,
52 T_LIST = 15,
53 T_UTF8 = 16,
54 T_UTF16 = 17
Mark Slee8d7e1f62006-06-07 06:48:56 +000055};
56
57/**
Mark Sleef5f2be42006-09-05 21:05:31 +000058 * Enumerated definition of the message types that the Thrift protocol
59 * supports.
Marc Slemko16698852006-08-04 03:16:10 +000060 */
61enum TMessageType {
62 T_CALL = 1,
Mark Sleef9831082007-02-20 20:59:21 +000063 T_REPLY = 2,
64 T_EXCEPTION = 3
Marc Slemko16698852006-08-04 03:16:10 +000065};
66
67/**
Mark Sleee8540632006-05-30 09:24:40 +000068 * Abstract class for a thrift protocol driver. These are all the methods that
69 * a protocol must implement. Essentially, there must be some way of reading
70 * and writing all the base types, plus a mechanism for writing out structs
71 * with indexed fields. Also notice that all methods are strictly const. This
72 * is by design. Protcol impelementations may NOT keep state, because the
73 * same TProtocol object may be used simultaneously by multiple threads. This
74 * theoretically introduces some limititations into the possible protocol
75 * formats, but with the benefit of performance, clarity, and simplicity.
76 *
77 * @author Mark Slee <mcslee@facebook.com>
78 */
79class TProtocol {
80 public:
81 virtual ~TProtocol() {}
82
83 /**
Mark Slee8d7e1f62006-06-07 06:48:56 +000084 * Writing functions.
Mark Sleee8540632006-05-30 09:24:40 +000085 */
86
Mark Slee4af6ed72006-10-25 19:02:49 +000087 virtual uint32_t writeMessageBegin(const std::string name,
Marc Slemko0b4ffa92006-08-11 02:49:29 +000088 const TMessageType messageType,
Mark Slee4af6ed72006-10-25 19:02:49 +000089 const int32_t seqid) = 0;
Marc Slemko16698852006-08-04 03:16:10 +000090
Mark Slee4af6ed72006-10-25 19:02:49 +000091 virtual uint32_t writeMessageEnd() = 0;
Marc Slemko16698852006-08-04 03:16:10 +000092
93
Mark Slee4af6ed72006-10-25 19:02:49 +000094 virtual uint32_t writeStructBegin(const std::string& name) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +000095
Mark Slee4af6ed72006-10-25 19:02:49 +000096 virtual uint32_t writeStructEnd() = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +000097
Mark Slee4af6ed72006-10-25 19:02:49 +000098 virtual uint32_t writeFieldBegin(const std::string& name,
Marc Slemko0b4ffa92006-08-11 02:49:29 +000099 const TType fieldType,
Mark Slee4af6ed72006-10-25 19:02:49 +0000100 const int16_t fieldId) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000101
Mark Slee4af6ed72006-10-25 19:02:49 +0000102 virtual uint32_t writeFieldEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000103
Mark Slee4af6ed72006-10-25 19:02:49 +0000104 virtual uint32_t writeFieldStop() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000105
Mark Slee4af6ed72006-10-25 19:02:49 +0000106 virtual uint32_t writeMapBegin(const TType keyType,
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000107 const TType valType,
Mark Slee4af6ed72006-10-25 19:02:49 +0000108 const uint32_t size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000109
Mark Slee4af6ed72006-10-25 19:02:49 +0000110 virtual uint32_t writeMapEnd() = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000111
Mark Slee4af6ed72006-10-25 19:02:49 +0000112 virtual uint32_t writeListBegin(const TType elemType,
113 const uint32_t size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000114
Mark Slee4af6ed72006-10-25 19:02:49 +0000115 virtual uint32_t writeListEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000116
Mark Slee4af6ed72006-10-25 19:02:49 +0000117 virtual uint32_t writeSetBegin(const TType elemType,
118 const uint32_t size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000119
Mark Slee4af6ed72006-10-25 19:02:49 +0000120 virtual uint32_t writeSetEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000121
Mark Slee4af6ed72006-10-25 19:02:49 +0000122 virtual uint32_t writeBool(const bool value) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000123
Mark Slee4af6ed72006-10-25 19:02:49 +0000124 virtual uint32_t writeByte(const int8_t byte) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000125
Mark Slee4af6ed72006-10-25 19:02:49 +0000126 virtual uint32_t writeI16(const int16_t i16) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000127
Mark Slee4af6ed72006-10-25 19:02:49 +0000128 virtual uint32_t writeI32(const int32_t i32) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000129
Mark Slee4af6ed72006-10-25 19:02:49 +0000130 virtual uint32_t writeI64(const int64_t i64) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000131
Mark Slee4af6ed72006-10-25 19:02:49 +0000132 virtual uint32_t writeDouble(const double dub) = 0;
Mark Sleec98d0502006-09-06 02:42:25 +0000133
Mark Slee4af6ed72006-10-25 19:02:49 +0000134 virtual uint32_t writeString(const std::string& str) = 0;
Mark Sleee8540632006-05-30 09:24:40 +0000135
136 /**
Mark Slee8d7e1f62006-06-07 06:48:56 +0000137 * Reading functions
Mark Sleee8540632006-05-30 09:24:40 +0000138 */
139
Mark Slee4af6ed72006-10-25 19:02:49 +0000140 virtual uint32_t readMessageBegin(std::string& name,
Marc Slemko91f67482006-08-11 23:58:57 +0000141 TMessageType& messageType,
Mark Slee4af6ed72006-10-25 19:02:49 +0000142 int32_t& seqid) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000143
Mark Slee4af6ed72006-10-25 19:02:49 +0000144 virtual uint32_t readMessageEnd() = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000145
Mark Slee4af6ed72006-10-25 19:02:49 +0000146 virtual uint32_t readStructBegin(std::string& name) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000147
Mark Slee4af6ed72006-10-25 19:02:49 +0000148 virtual uint32_t readStructEnd() = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000149
Mark Slee4af6ed72006-10-25 19:02:49 +0000150 virtual uint32_t readFieldBegin(std::string& name,
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000151 TType& fieldType,
Mark Slee4af6ed72006-10-25 19:02:49 +0000152 int16_t& fieldId) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000153
Mark Slee4af6ed72006-10-25 19:02:49 +0000154 virtual uint32_t readFieldEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000155
Mark Slee4af6ed72006-10-25 19:02:49 +0000156 virtual uint32_t readMapBegin(TType& keyType,
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000157 TType& valType,
Mark Slee4af6ed72006-10-25 19:02:49 +0000158 uint32_t& size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000159
Mark Slee4af6ed72006-10-25 19:02:49 +0000160 virtual uint32_t readMapEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000161
Mark Slee4af6ed72006-10-25 19:02:49 +0000162 virtual uint32_t readListBegin(TType& elemType,
163 uint32_t& size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000164
Mark Slee4af6ed72006-10-25 19:02:49 +0000165 virtual uint32_t readListEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000166
Mark Slee4af6ed72006-10-25 19:02:49 +0000167 virtual uint32_t readSetBegin(TType& elemType,
168 uint32_t& size) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000169
Mark Slee4af6ed72006-10-25 19:02:49 +0000170 virtual uint32_t readSetEnd() = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000171
Mark Slee4af6ed72006-10-25 19:02:49 +0000172 virtual uint32_t readBool(bool& value) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000173
Mark Slee4af6ed72006-10-25 19:02:49 +0000174 virtual uint32_t readByte(int8_t& byte) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000175
Mark Slee4af6ed72006-10-25 19:02:49 +0000176 virtual uint32_t readI16(int16_t& i16) = 0;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000177
Mark Slee4af6ed72006-10-25 19:02:49 +0000178 virtual uint32_t readI32(int32_t& i32) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000179
Mark Slee4af6ed72006-10-25 19:02:49 +0000180 virtual uint32_t readI64(int64_t& i64) = 0;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000181
Mark Slee4af6ed72006-10-25 19:02:49 +0000182 virtual uint32_t readDouble(double& dub) = 0;
Mark Sleec98d0502006-09-06 02:42:25 +0000183
Mark Slee4af6ed72006-10-25 19:02:49 +0000184 virtual uint32_t readString(std::string& str) = 0;
Mark Sleee8540632006-05-30 09:24:40 +0000185
186 /**
Mark Slee8d7e1f62006-06-07 06:48:56 +0000187 * Method to arbitrarily skip over data.
Mark Sleee8540632006-05-30 09:24:40 +0000188 */
Mark Slee4af6ed72006-10-25 19:02:49 +0000189 uint32_t skip(TType type) {
Mark Slee8d7e1f62006-06-07 06:48:56 +0000190 switch (type) {
Mark Slee78f58e22006-09-02 04:17:07 +0000191 case T_BOOL:
192 {
193 bool boolv;
Mark Slee4af6ed72006-10-25 19:02:49 +0000194 return readBool(boolv);
Mark Slee78f58e22006-09-02 04:17:07 +0000195 }
Mark Slee8d7e1f62006-06-07 06:48:56 +0000196 case T_BYTE:
197 {
Mark Slee78f58e22006-09-02 04:17:07 +0000198 int8_t bytev;
Mark Slee4af6ed72006-10-25 19:02:49 +0000199 return readByte(bytev);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000200 }
Mark Sleecfc01932006-09-01 22:18:16 +0000201 case T_I16:
Mark Slee8d7e1f62006-06-07 06:48:56 +0000202 {
Mark Sleecfc01932006-09-01 22:18:16 +0000203 int16_t i16;
Mark Slee4af6ed72006-10-25 19:02:49 +0000204 return readI16(i16);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000205 }
206 case T_I32:
207 {
208 int32_t i32;
Mark Slee4af6ed72006-10-25 19:02:49 +0000209 return readI32(i32);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000210 }
Mark Slee8d7e1f62006-06-07 06:48:56 +0000211 case T_I64:
212 {
213 int64_t i64;
Mark Slee4af6ed72006-10-25 19:02:49 +0000214 return readI64(i64);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000215 }
Mark Sleec98d0502006-09-06 02:42:25 +0000216 case T_DOUBLE:
217 {
218 double dub;
Mark Slee4af6ed72006-10-25 19:02:49 +0000219 return readDouble(dub);
Mark Sleec98d0502006-09-06 02:42:25 +0000220 }
Mark Slee8d7e1f62006-06-07 06:48:56 +0000221 case T_STRING:
222 {
223 std::string str;
Mark Slee4af6ed72006-10-25 19:02:49 +0000224 return readString(str);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000225 }
226 case T_STRUCT:
227 {
228 uint32_t result = 0;
229 std::string name;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000230 int16_t fid;
Mark Slee8d7e1f62006-06-07 06:48:56 +0000231 TType ftype;
Mark Slee4af6ed72006-10-25 19:02:49 +0000232 result += readStructBegin(name);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000233 while (true) {
Mark Slee4af6ed72006-10-25 19:02:49 +0000234 result += readFieldBegin(name, ftype, fid);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000235 if (ftype == T_STOP) {
236 break;
237 }
Mark Slee4af6ed72006-10-25 19:02:49 +0000238 result += skip(ftype);
239 result += readFieldEnd();
Mark Slee8d7e1f62006-06-07 06:48:56 +0000240 }
Mark Slee4af6ed72006-10-25 19:02:49 +0000241 result += readStructEnd();
Mark Slee8d7e1f62006-06-07 06:48:56 +0000242 return result;
243 }
244 case T_MAP:
245 {
246 uint32_t result = 0;
247 TType keyType;
248 TType valType;
Marc Slemkob09f5882006-08-23 22:03:34 +0000249 uint32_t i, size;
Mark Slee4af6ed72006-10-25 19:02:49 +0000250 result += readMapBegin(keyType, valType, size);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000251 for (i = 0; i < size; i++) {
Mark Slee4af6ed72006-10-25 19:02:49 +0000252 result += skip(keyType);
253 result += skip(valType);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000254 }
Mark Slee4af6ed72006-10-25 19:02:49 +0000255 result += readMapEnd();
Mark Slee8d7e1f62006-06-07 06:48:56 +0000256 return result;
257 }
258 case T_SET:
259 {
260 uint32_t result = 0;
261 TType elemType;
Marc Slemkob09f5882006-08-23 22:03:34 +0000262 uint32_t i, size;
Mark Slee4af6ed72006-10-25 19:02:49 +0000263 result += readSetBegin(elemType, size);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000264 for (i = 0; i < size; i++) {
Mark Slee4af6ed72006-10-25 19:02:49 +0000265 result += skip(elemType);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000266 }
Mark Slee4af6ed72006-10-25 19:02:49 +0000267 result += readSetEnd();
Mark Slee8d7e1f62006-06-07 06:48:56 +0000268 return result;
269 }
270 case T_LIST:
271 {
272 uint32_t result = 0;
273 TType elemType;
Marc Slemkob09f5882006-08-23 22:03:34 +0000274 uint32_t i, size;
Mark Slee4af6ed72006-10-25 19:02:49 +0000275 result += readListBegin(elemType, size);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000276 for (i = 0; i < size; i++) {
Mark Slee4af6ed72006-10-25 19:02:49 +0000277 result += skip(elemType);
Mark Slee8d7e1f62006-06-07 06:48:56 +0000278 }
Mark Slee4af6ed72006-10-25 19:02:49 +0000279 result += readListEnd();
Mark Slee8d7e1f62006-06-07 06:48:56 +0000280 return result;
281 }
282 default:
283 return 0;
284 }
285 }
Mark Sleee8540632006-05-30 09:24:40 +0000286
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000287 inline shared_ptr<TTransport> getTransport() {
Mark Slee43b6c632007-02-07 00:54:17 +0000288 return ptrans_;
Mark Slee4af6ed72006-10-25 19:02:49 +0000289 }
290
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000291 // TODO: remove these two calls, they are for backwards
292 // compatibility
293 inline shared_ptr<TTransport> getInputTransport() {
Mark Slee43b6c632007-02-07 00:54:17 +0000294 return ptrans_;
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000295 }
296 inline shared_ptr<TTransport> getOutputTransport() {
Mark Slee43b6c632007-02-07 00:54:17 +0000297 return ptrans_;
Mark Slee4af6ed72006-10-25 19:02:49 +0000298 }
299
Mark Sleee8540632006-05-30 09:24:40 +0000300 protected:
Mark Slee43b6c632007-02-07 00:54:17 +0000301 TProtocol(shared_ptr<TTransport> ptrans):
302 ptrans_(ptrans) {
303 trans_ = ptrans.get();
304 }
Mark Slee4af6ed72006-10-25 19:02:49 +0000305
Mark Slee43b6c632007-02-07 00:54:17 +0000306 shared_ptr<TTransport> ptrans_;
307 TTransport* trans_;
Mark Slee4af6ed72006-10-25 19:02:49 +0000308
309 private:
Mark Sleee8540632006-05-30 09:24:40 +0000310 TProtocol() {}
311};
312
Mark Slee4af6ed72006-10-25 19:02:49 +0000313/**
314 * Constructs input and output protocol objects given transports.
315 */
316class TProtocolFactory {
317 public:
318 TProtocolFactory() {}
319
320 virtual ~TProtocolFactory() {}
321
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000322 virtual boost::shared_ptr<TProtocol> getProtocol(boost::shared_ptr<TTransport> trans) = 0;
Mark Slee4af6ed72006-10-25 19:02:49 +0000323};
324
Marc Slemko6f038a72006-08-03 18:58:09 +0000325}}} // facebook::thrift::protocol
326
Mark Sleef5f2be42006-09-05 21:05:31 +0000327#endif // #define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1