blob: 438ed8914763600ccd54da591df53e11265d8379 [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 */
David Reiss4e7530d2007-09-04 21:49:53 +000019
20#ifndef _THRIFT_PROTOCOL_TDENSEPROTOCOL_H_
21#define _THRIFT_PROTOCOL_TDENSEPROTOCOL_H_ 1
22
23#include "TBinaryProtocol.h"
24
T Jake Lucianib5e62212009-01-31 22:36:20 +000025namespace apache { namespace thrift { namespace protocol {
David Reiss4e7530d2007-09-04 21:49:53 +000026
27/**
David Reiss4e7530d2007-09-04 21:49:53 +000028 * !!!WARNING!!!
29 * This class is still highly experimental. Incompatible changes
30 * WILL be made to it without notice. DO NOT USE IT YET unless
31 * you are coordinating your testing with the author.
32 *
David Reissce161a92007-09-11 22:09:42 +000033 * The dense protocol is designed to use as little space as possible.
34 *
35 * There are two types of dense protocol instances. Standalone instances
David Reiss0c90f6f2008-02-06 22:18:40 +000036 * are not used for RPC and just encoded and decode structures of
David Reissce161a92007-09-11 22:09:42 +000037 * a predetermined type. Non-standalone instances are used for RPC.
38 * Currently, only standalone instances exist.
39 *
40 * To use a standalone dense protocol object, you must set the type_spec
41 * property (either in the constructor, or with setTypeSpec) to the local
42 * reflection TypeSpec of the structures you will write to (or read from) the
43 * protocol instance.
44 *
45 * BEST PRACTICES:
46 * - Never use optional for primitives or containers.
47 * - Only use optional for structures if they are very big and very rarely set.
48 * - All integers are variable-length, so you can use i64 without bloating.
49 * - NEVER EVER change the struct definitions IN ANY WAY without either
50 * changing your cache keys or talking to dreiss.
51 *
David Reiss4e7530d2007-09-04 21:49:53 +000052 * TODO(dreiss): New class write with old meta.
53 *
54 * We override all of TBinaryProtocol's methods.
55 * We inherit so that we can can explicitly call TBPs's primitive-writing
56 * methods within our versions.
57 *
David Reiss4e7530d2007-09-04 21:49:53 +000058 */
David Reiss6806fb82010-10-06 17:09:52 +000059class TDenseProtocol
60 : public TVirtualProtocol<TDenseProtocol, TBinaryProtocol> {
David Reiss4e7530d2007-09-04 21:49:53 +000061 protected:
62 static const int32_t VERSION_MASK = 0xffff0000;
David Reisse67c0e62007-09-07 01:34:12 +000063 // VERSION_1 (0x80010000) is taken by TBinaryProtocol.
David Reiss4e7530d2007-09-04 21:49:53 +000064 static const int32_t VERSION_2 = 0x80020000;
65
66 public:
T Jake Lucianib5e62212009-01-31 22:36:20 +000067 typedef apache::thrift::reflection::local::TypeSpec TypeSpec;
David Reissce161a92007-09-11 22:09:42 +000068 static const int FP_PREFIX_LEN;
David Reiss4e7530d2007-09-04 21:49:53 +000069
David Reissce161a92007-09-11 22:09:42 +000070 /**
71 * @param tran The transport to use.
72 * @param type_spec The TypeSpec of the structures using this protocol.
73 */
David Reiss4e7530d2007-09-04 21:49:53 +000074 TDenseProtocol(boost::shared_ptr<TTransport> trans,
75 TypeSpec* type_spec = NULL) :
David Reiss6806fb82010-10-06 17:09:52 +000076 TVirtualProtocol<TDenseProtocol, TBinaryProtocol>(trans),
David Reissce161a92007-09-11 22:09:42 +000077 type_spec_(type_spec),
78 standalone_(true)
79 {}
David Reiss4e7530d2007-09-04 21:49:53 +000080
81 void setTypeSpec(TypeSpec* type_spec) {
82 type_spec_ = type_spec;
83 }
84 TypeSpec* getTypeSpec() {
85 return type_spec_;
86 }
87
88
89 /*
90 * Writing functions.
91 */
92
David Reiss6806fb82010-10-06 17:09:52 +000093 uint32_t writeMessageBegin(const std::string& name,
94 const TMessageType messageType,
95 const int32_t seqid);
David Reiss4e7530d2007-09-04 21:49:53 +000096
David Reiss6806fb82010-10-06 17:09:52 +000097 uint32_t writeMessageEnd();
David Reiss4e7530d2007-09-04 21:49:53 +000098
99
David Reiss6806fb82010-10-06 17:09:52 +0000100 uint32_t writeStructBegin(const char* name);
David Reiss4e7530d2007-09-04 21:49:53 +0000101
David Reiss6806fb82010-10-06 17:09:52 +0000102 uint32_t writeStructEnd();
David Reiss4e7530d2007-09-04 21:49:53 +0000103
David Reiss6806fb82010-10-06 17:09:52 +0000104 uint32_t writeFieldBegin(const char* name,
105 const TType fieldType,
106 const int16_t fieldId);
David Reiss4e7530d2007-09-04 21:49:53 +0000107
David Reiss6806fb82010-10-06 17:09:52 +0000108 uint32_t writeFieldEnd();
David Reiss4e7530d2007-09-04 21:49:53 +0000109
David Reiss6806fb82010-10-06 17:09:52 +0000110 uint32_t writeFieldStop();
David Reiss4e7530d2007-09-04 21:49:53 +0000111
David Reiss6806fb82010-10-06 17:09:52 +0000112 uint32_t writeMapBegin(const TType keyType,
113 const TType valType,
114 const uint32_t size);
David Reiss4e7530d2007-09-04 21:49:53 +0000115
David Reiss6806fb82010-10-06 17:09:52 +0000116 uint32_t writeMapEnd();
David Reiss4e7530d2007-09-04 21:49:53 +0000117
David Reiss6806fb82010-10-06 17:09:52 +0000118 uint32_t writeListBegin(const TType elemType, const uint32_t size);
David Reiss4e7530d2007-09-04 21:49:53 +0000119
David Reiss6806fb82010-10-06 17:09:52 +0000120 uint32_t writeListEnd();
David Reiss4e7530d2007-09-04 21:49:53 +0000121
David Reiss6806fb82010-10-06 17:09:52 +0000122 uint32_t writeSetBegin(const TType elemType, const uint32_t size);
David Reiss4e7530d2007-09-04 21:49:53 +0000123
David Reiss6806fb82010-10-06 17:09:52 +0000124 uint32_t writeSetEnd();
David Reiss4e7530d2007-09-04 21:49:53 +0000125
David Reiss6806fb82010-10-06 17:09:52 +0000126 uint32_t writeBool(const bool value);
David Reiss4e7530d2007-09-04 21:49:53 +0000127
David Reiss6806fb82010-10-06 17:09:52 +0000128 uint32_t writeByte(const int8_t byte);
David Reiss4e7530d2007-09-04 21:49:53 +0000129
David Reiss6806fb82010-10-06 17:09:52 +0000130 uint32_t writeI16(const int16_t i16);
David Reiss4e7530d2007-09-04 21:49:53 +0000131
David Reiss6806fb82010-10-06 17:09:52 +0000132 uint32_t writeI32(const int32_t i32);
David Reiss4e7530d2007-09-04 21:49:53 +0000133
David Reiss6806fb82010-10-06 17:09:52 +0000134 uint32_t writeI64(const int64_t i64);
David Reiss4e7530d2007-09-04 21:49:53 +0000135
David Reiss6806fb82010-10-06 17:09:52 +0000136 uint32_t writeDouble(const double dub);
David Reiss4e7530d2007-09-04 21:49:53 +0000137
David Reiss6806fb82010-10-06 17:09:52 +0000138 uint32_t writeString(const std::string& str);
David Reiss4e7530d2007-09-04 21:49:53 +0000139
David Reiss6806fb82010-10-06 17:09:52 +0000140 uint32_t writeBinary(const std::string& str);
David Reissc005b1b2008-02-15 01:38:18 +0000141
David Reiss4e7530d2007-09-04 21:49:53 +0000142
143 /*
144 * Helper writing functions (don't do state transitions).
145 */
146 inline uint32_t subWriteI32(const int32_t i32);
147
David Reisse67c0e62007-09-07 01:34:12 +0000148 inline uint32_t subWriteString(const std::string& str);
149
David Reiss4e7530d2007-09-04 21:49:53 +0000150 uint32_t subWriteBool(const bool value) {
151 return TBinaryProtocol::writeBool(value);
152 }
153
David Reiss4e7530d2007-09-04 21:49:53 +0000154
155 /*
156 * Reading functions
157 */
158
159 uint32_t readMessageBegin(std::string& name,
160 TMessageType& messageType,
161 int32_t& seqid);
162
163 uint32_t readMessageEnd();
164
165 uint32_t readStructBegin(std::string& name);
166
167 uint32_t readStructEnd();
168
169 uint32_t readFieldBegin(std::string& name,
170 TType& fieldType,
171 int16_t& fieldId);
172
173 uint32_t readFieldEnd();
174
175 uint32_t readMapBegin(TType& keyType,
176 TType& valType,
177 uint32_t& size);
178
179 uint32_t readMapEnd();
180
181 uint32_t readListBegin(TType& elemType,
182 uint32_t& size);
183
184 uint32_t readListEnd();
185
186 uint32_t readSetBegin(TType& elemType,
187 uint32_t& size);
188
189 uint32_t readSetEnd();
190
191 uint32_t readBool(bool& value);
David Reiss8dfc7322010-10-06 17:09:58 +0000192 // Provide the default readBool() implementation for std::vector<bool>
193 using TVirtualProtocol<TDenseProtocol, TBinaryProtocol>::readBool;
David Reiss4e7530d2007-09-04 21:49:53 +0000194
195 uint32_t readByte(int8_t& byte);
196
197 uint32_t readI16(int16_t& i16);
198
199 uint32_t readI32(int32_t& i32);
200
201 uint32_t readI64(int64_t& i64);
202
203 uint32_t readDouble(double& dub);
204
205 uint32_t readString(std::string& str);
206
David Reissc005b1b2008-02-15 01:38:18 +0000207 uint32_t readBinary(std::string& str);
David Reiss4e7530d2007-09-04 21:49:53 +0000208
209 /*
210 * Helper reading functions (don't do state transitions).
211 */
David Reisse67c0e62007-09-07 01:34:12 +0000212 inline uint32_t subReadI32(int32_t& i32);
213
214 inline uint32_t subReadString(std::string& str);
David Reiss4e7530d2007-09-04 21:49:53 +0000215
216 uint32_t subReadBool(bool& value) {
217 return TBinaryProtocol::readBool(value);
218 }
219
David Reiss4e7530d2007-09-04 21:49:53 +0000220
221 private:
222
David Reissce161a92007-09-11 22:09:42 +0000223 // Implementation functions, documented in the .cpp.
David Reiss4e7530d2007-09-04 21:49:53 +0000224 inline void checkTType(const TType ttype);
225 inline void stateTransition();
226
David Reisse67c0e62007-09-07 01:34:12 +0000227 // Read and write variable-length integers.
228 // Uses the same technique as the MIDI file format.
David Reissce161a92007-09-11 22:09:42 +0000229 inline uint32_t vlqRead(uint64_t& vlq);
230 inline uint32_t vlqWrite(uint64_t vlq);
David Reisse67c0e62007-09-07 01:34:12 +0000231
David Reissce161a92007-09-11 22:09:42 +0000232 // Called before throwing an exception to make the object reusable.
233 void resetState() {
234 ts_stack_.clear();
235 idx_stack_.clear();
236 mkv_stack_.clear();
237 }
238
239 // TypeSpec of the top-level structure to write,
240 // for standalone protocol objects.
David Reiss4e7530d2007-09-04 21:49:53 +0000241 TypeSpec* type_spec_;
242
243 std::vector<TypeSpec*> ts_stack_; // TypeSpec stack.
244 std::vector<int> idx_stack_; // InDeX stack.
245 std::vector<bool> mkv_stack_; // Map Key/Vlue stack.
246 // True = key, False = value.
247
David Reissce161a92007-09-11 22:09:42 +0000248 // True iff this is a standalone instance (no RPC).
249 bool standalone_;
David Reiss4e7530d2007-09-04 21:49:53 +0000250};
251
T Jake Lucianib5e62212009-01-31 22:36:20 +0000252}}} // apache::thrift::protocol
David Reiss4e7530d2007-09-04 21:49:53 +0000253
254#endif // #ifndef _THRIFT_PROTOCOL_TDENSEPROTOCOL_H_