blob: 0902e15f31b2198502e4dbae5c776f49cbcf7c79 [file] [log] [blame]
David Reiss4e7530d2007-09-04 21:49:53 +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
7#ifndef _THRIFT_PROTOCOL_TDENSEPROTOCOL_H_
8#define _THRIFT_PROTOCOL_TDENSEPROTOCOL_H_ 1
9
10#include "TBinaryProtocol.h"
11
12namespace facebook { namespace thrift { namespace protocol {
13
14/**
David Reiss4e7530d2007-09-04 21:49:53 +000015 * !!!WARNING!!!
16 * This class is still highly experimental. Incompatible changes
17 * WILL be made to it without notice. DO NOT USE IT YET unless
18 * you are coordinating your testing with the author.
19 *
David Reissce161a92007-09-11 22:09:42 +000020 * The dense protocol is designed to use as little space as possible.
21 *
22 * There are two types of dense protocol instances. Standalone instances
23 * are not used for RPC and just encoded and decode structures of
24 * a predetermined type. Non-standalone instances are used for RPC.
25 * Currently, only standalone instances exist.
26 *
27 * To use a standalone dense protocol object, you must set the type_spec
28 * property (either in the constructor, or with setTypeSpec) to the local
29 * reflection TypeSpec of the structures you will write to (or read from) the
30 * protocol instance.
31 *
32 * BEST PRACTICES:
33 * - Never use optional for primitives or containers.
34 * - Only use optional for structures if they are very big and very rarely set.
35 * - All integers are variable-length, so you can use i64 without bloating.
36 * - NEVER EVER change the struct definitions IN ANY WAY without either
37 * changing your cache keys or talking to dreiss.
38 *
David Reiss4e7530d2007-09-04 21:49:53 +000039 * TODO(dreiss): New class write with old meta.
40 *
41 * We override all of TBinaryProtocol's methods.
42 * We inherit so that we can can explicitly call TBPs's primitive-writing
43 * methods within our versions.
44 *
45 * @author David Reiss <dreiss@facebook.com>
46 */
47class TDenseProtocol : public TBinaryProtocol {
48 protected:
49 static const int32_t VERSION_MASK = 0xffff0000;
David Reisse67c0e62007-09-07 01:34:12 +000050 // VERSION_1 (0x80010000) is taken by TBinaryProtocol.
David Reiss4e7530d2007-09-04 21:49:53 +000051 static const int32_t VERSION_2 = 0x80020000;
52
53 public:
54 typedef facebook::thrift::reflection::local::TypeSpec TypeSpec;
David Reissce161a92007-09-11 22:09:42 +000055 static const int FP_PREFIX_LEN;
David Reiss4e7530d2007-09-04 21:49:53 +000056
David Reissce161a92007-09-11 22:09:42 +000057 /**
58 * @param tran The transport to use.
59 * @param type_spec The TypeSpec of the structures using this protocol.
60 */
David Reiss4e7530d2007-09-04 21:49:53 +000061 TDenseProtocol(boost::shared_ptr<TTransport> trans,
62 TypeSpec* type_spec = NULL) :
63 TBinaryProtocol(trans),
David Reissce161a92007-09-11 22:09:42 +000064 type_spec_(type_spec),
65 standalone_(true)
66 {}
David Reiss4e7530d2007-09-04 21:49:53 +000067
68 void setTypeSpec(TypeSpec* type_spec) {
69 type_spec_ = type_spec;
70 }
71 TypeSpec* getTypeSpec() {
72 return type_spec_;
73 }
74
75
76 /*
77 * Writing functions.
78 */
79
80 virtual uint32_t writeMessageBegin(const std::string& name,
81 const TMessageType messageType,
82 const int32_t seqid);
83
84 virtual uint32_t writeMessageEnd();
85
86
87 virtual uint32_t writeStructBegin(const std::string& name);
88
89 virtual uint32_t writeStructEnd();
90
91 virtual uint32_t writeFieldBegin(const std::string& name,
92 const TType fieldType,
93 const int16_t fieldId);
94
95 virtual uint32_t writeFieldEnd();
96
97 virtual uint32_t writeFieldStop();
98
99 virtual uint32_t writeMapBegin(const TType keyType,
100 const TType valType,
101 const uint32_t size);
102
103 virtual uint32_t writeMapEnd();
104
105 virtual uint32_t writeListBegin(const TType elemType,
106 const uint32_t size);
107
108 virtual uint32_t writeListEnd();
109
110 virtual uint32_t writeSetBegin(const TType elemType,
111 const uint32_t size);
112
113 virtual uint32_t writeSetEnd();
114
115 virtual uint32_t writeBool(const bool value);
116
117 virtual uint32_t writeByte(const int8_t byte);
118
119 virtual uint32_t writeI16(const int16_t i16);
120
121 virtual uint32_t writeI32(const int32_t i32);
122
123 virtual uint32_t writeI64(const int64_t i64);
124
125 virtual uint32_t writeDouble(const double dub);
126
127 virtual uint32_t writeString(const std::string& str);
128
129
130 /*
131 * Helper writing functions (don't do state transitions).
132 */
133 inline uint32_t subWriteI32(const int32_t i32);
134
David Reisse67c0e62007-09-07 01:34:12 +0000135 inline uint32_t subWriteString(const std::string& str);
136
David Reiss4e7530d2007-09-04 21:49:53 +0000137 uint32_t subWriteBool(const bool value) {
138 return TBinaryProtocol::writeBool(value);
139 }
140
David Reiss4e7530d2007-09-04 21:49:53 +0000141
142 /*
143 * Reading functions
144 */
145
146 uint32_t readMessageBegin(std::string& name,
147 TMessageType& messageType,
148 int32_t& seqid);
149
150 uint32_t readMessageEnd();
151
152 uint32_t readStructBegin(std::string& name);
153
154 uint32_t readStructEnd();
155
156 uint32_t readFieldBegin(std::string& name,
157 TType& fieldType,
158 int16_t& fieldId);
159
160 uint32_t readFieldEnd();
161
162 uint32_t readMapBegin(TType& keyType,
163 TType& valType,
164 uint32_t& size);
165
166 uint32_t readMapEnd();
167
168 uint32_t readListBegin(TType& elemType,
169 uint32_t& size);
170
171 uint32_t readListEnd();
172
173 uint32_t readSetBegin(TType& elemType,
174 uint32_t& size);
175
176 uint32_t readSetEnd();
177
178 uint32_t readBool(bool& value);
179
180 uint32_t readByte(int8_t& byte);
181
182 uint32_t readI16(int16_t& i16);
183
184 uint32_t readI32(int32_t& i32);
185
186 uint32_t readI64(int64_t& i64);
187
188 uint32_t readDouble(double& dub);
189
190 uint32_t readString(std::string& str);
191
192
193 /*
194 * Helper reading functions (don't do state transitions).
195 */
David Reisse67c0e62007-09-07 01:34:12 +0000196 inline uint32_t subReadI32(int32_t& i32);
197
198 inline uint32_t subReadString(std::string& str);
David Reiss4e7530d2007-09-04 21:49:53 +0000199
200 uint32_t subReadBool(bool& value) {
201 return TBinaryProtocol::readBool(value);
202 }
203
David Reiss4e7530d2007-09-04 21:49:53 +0000204
205 private:
206
David Reissce161a92007-09-11 22:09:42 +0000207 // Implementation functions, documented in the .cpp.
David Reiss4e7530d2007-09-04 21:49:53 +0000208 inline void checkTType(const TType ttype);
209 inline void stateTransition();
210
David Reisse67c0e62007-09-07 01:34:12 +0000211 // Read and write variable-length integers.
212 // Uses the same technique as the MIDI file format.
David Reissce161a92007-09-11 22:09:42 +0000213 inline uint32_t vlqRead(uint64_t& vlq);
214 inline uint32_t vlqWrite(uint64_t vlq);
David Reisse67c0e62007-09-07 01:34:12 +0000215
David Reissce161a92007-09-11 22:09:42 +0000216 // Called before throwing an exception to make the object reusable.
217 void resetState() {
218 ts_stack_.clear();
219 idx_stack_.clear();
220 mkv_stack_.clear();
221 }
222
223 // TypeSpec of the top-level structure to write,
224 // for standalone protocol objects.
David Reiss4e7530d2007-09-04 21:49:53 +0000225 TypeSpec* type_spec_;
226
227 std::vector<TypeSpec*> ts_stack_; // TypeSpec stack.
228 std::vector<int> idx_stack_; // InDeX stack.
229 std::vector<bool> mkv_stack_; // Map Key/Vlue stack.
230 // True = key, False = value.
231
David Reissce161a92007-09-11 22:09:42 +0000232 // True iff this is a standalone instance (no RPC).
233 bool standalone_;
David Reiss4e7530d2007-09-04 21:49:53 +0000234};
235
236}}} // facebook::thrift::protocol
237
238#endif // #ifndef _THRIFT_PROTOCOL_TDENSEPROTOCOL_H_