blob: d7a119a1eda9b2ad06db7c5dc801ff931609ee63 [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
Roger Meier4285ba22013-06-10 21:17:23 +020023#include <thrift/protocol/TBinaryProtocol.h>
David Reiss4e7530d2007-09-04 21:49:53 +000024
Konrad Grochowski16a23a62014-11-13 15:33:38 +010025namespace apache {
26namespace thrift {
27namespace protocol {
David Reiss4e7530d2007-09-04 21:49:53 +000028
29/**
David Reiss4e7530d2007-09-04 21:49:53 +000030 * !!!WARNING!!!
31 * This class is still highly experimental. Incompatible changes
32 * WILL be made to it without notice. DO NOT USE IT YET unless
33 * you are coordinating your testing with the author.
34 *
David Reissce161a92007-09-11 22:09:42 +000035 * The dense protocol is designed to use as little space as possible.
36 *
37 * There are two types of dense protocol instances. Standalone instances
David Reiss0c90f6f2008-02-06 22:18:40 +000038 * are not used for RPC and just encoded and decode structures of
David Reissce161a92007-09-11 22:09:42 +000039 * a predetermined type. Non-standalone instances are used for RPC.
40 * Currently, only standalone instances exist.
41 *
42 * To use a standalone dense protocol object, you must set the type_spec
43 * property (either in the constructor, or with setTypeSpec) to the local
44 * reflection TypeSpec of the structures you will write to (or read from) the
45 * protocol instance.
46 *
47 * BEST PRACTICES:
48 * - Never use optional for primitives or containers.
49 * - Only use optional for structures if they are very big and very rarely set.
50 * - All integers are variable-length, so you can use i64 without bloating.
51 * - NEVER EVER change the struct definitions IN ANY WAY without either
52 * changing your cache keys or talking to dreiss.
53 *
David Reiss4e7530d2007-09-04 21:49:53 +000054 * TODO(dreiss): New class write with old meta.
55 *
56 * We override all of TBinaryProtocol's methods.
Konrad Grochowski67946982014-12-04 23:22:41 +010057 * We inherit so that we can explicitly call TBPs's primitive-writing
David Reiss4e7530d2007-09-04 21:49:53 +000058 * methods within our versions.
59 *
David Reiss4e7530d2007-09-04 21:49:53 +000060 */
Konrad Grochowski16a23a62014-11-13 15:33:38 +010061class TDenseProtocol : public TVirtualProtocol<TDenseProtocol, TBinaryProtocol> {
62protected:
Roger Meier406fc742011-12-08 11:32:21 +000063 static const int32_t VERSION_MASK = ((int32_t)0xffff0000);
David Reisse67c0e62007-09-07 01:34:12 +000064 // VERSION_1 (0x80010000) is taken by TBinaryProtocol.
Roger Meier406fc742011-12-08 11:32:21 +000065 static const int32_t VERSION_2 = ((int32_t)0x80020000);
David Reiss4e7530d2007-09-04 21:49:53 +000066
Konrad Grochowski16a23a62014-11-13 15:33:38 +010067public:
T Jake Lucianib5e62212009-01-31 22:36:20 +000068 typedef apache::thrift::reflection::local::TypeSpec TypeSpec;
David Reissce161a92007-09-11 22:09:42 +000069 static const int FP_PREFIX_LEN;
David Reiss4e7530d2007-09-04 21:49:53 +000070
David Reissce161a92007-09-11 22:09:42 +000071 /**
72 * @param tran The transport to use.
73 * @param type_spec The TypeSpec of the structures using this protocol.
74 */
Konrad Grochowski16a23a62014-11-13 15:33:38 +010075 TDenseProtocol(boost::shared_ptr<TTransport> trans, TypeSpec* type_spec = NULL)
76 : TVirtualProtocol<TDenseProtocol, TBinaryProtocol>(trans),
77 type_spec_(type_spec),
78 standalone_(true) {}
David Reiss4e7530d2007-09-04 21:49:53 +000079
Konrad Grochowski16a23a62014-11-13 15:33:38 +010080 void setTypeSpec(TypeSpec* type_spec) { type_spec_ = type_spec; }
81 TypeSpec* getTypeSpec() { return type_spec_; }
David Reiss4e7530d2007-09-04 21:49:53 +000082
83 /*
84 * Writing functions.
85 */
86
David Reiss6806fb82010-10-06 17:09:52 +000087 uint32_t writeMessageBegin(const std::string& name,
88 const TMessageType messageType,
89 const int32_t seqid);
David Reiss4e7530d2007-09-04 21:49:53 +000090
David Reiss6806fb82010-10-06 17:09:52 +000091 uint32_t writeMessageEnd();
David Reiss4e7530d2007-09-04 21:49:53 +000092
David Reiss6806fb82010-10-06 17:09:52 +000093 uint32_t writeStructBegin(const char* name);
David Reiss4e7530d2007-09-04 21:49:53 +000094
David Reiss6806fb82010-10-06 17:09:52 +000095 uint32_t writeStructEnd();
David Reiss4e7530d2007-09-04 21:49:53 +000096
Konrad Grochowski16a23a62014-11-13 15:33:38 +010097 uint32_t writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId);
David Reiss4e7530d2007-09-04 21:49:53 +000098
David Reiss6806fb82010-10-06 17:09:52 +000099 uint32_t writeFieldEnd();
David Reiss4e7530d2007-09-04 21:49:53 +0000100
David Reiss6806fb82010-10-06 17:09:52 +0000101 uint32_t writeFieldStop();
David Reiss4e7530d2007-09-04 21:49:53 +0000102
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100103 uint32_t writeMapBegin(const TType keyType, const TType valType, const uint32_t size);
David Reiss4e7530d2007-09-04 21:49:53 +0000104
David Reiss6806fb82010-10-06 17:09:52 +0000105 uint32_t writeMapEnd();
David Reiss4e7530d2007-09-04 21:49:53 +0000106
David Reiss6806fb82010-10-06 17:09:52 +0000107 uint32_t writeListBegin(const TType elemType, const uint32_t size);
David Reiss4e7530d2007-09-04 21:49:53 +0000108
David Reiss6806fb82010-10-06 17:09:52 +0000109 uint32_t writeListEnd();
David Reiss4e7530d2007-09-04 21:49:53 +0000110
David Reiss6806fb82010-10-06 17:09:52 +0000111 uint32_t writeSetBegin(const TType elemType, const uint32_t size);
David Reiss4e7530d2007-09-04 21:49:53 +0000112
David Reiss6806fb82010-10-06 17:09:52 +0000113 uint32_t writeSetEnd();
David Reiss4e7530d2007-09-04 21:49:53 +0000114
David Reiss6806fb82010-10-06 17:09:52 +0000115 uint32_t writeBool(const bool value);
David Reiss4e7530d2007-09-04 21:49:53 +0000116
David Reiss6806fb82010-10-06 17:09:52 +0000117 uint32_t writeByte(const int8_t byte);
David Reiss4e7530d2007-09-04 21:49:53 +0000118
David Reiss6806fb82010-10-06 17:09:52 +0000119 uint32_t writeI16(const int16_t i16);
David Reiss4e7530d2007-09-04 21:49:53 +0000120
David Reiss6806fb82010-10-06 17:09:52 +0000121 uint32_t writeI32(const int32_t i32);
David Reiss4e7530d2007-09-04 21:49:53 +0000122
David Reiss6806fb82010-10-06 17:09:52 +0000123 uint32_t writeI64(const int64_t i64);
David Reiss4e7530d2007-09-04 21:49:53 +0000124
David Reiss6806fb82010-10-06 17:09:52 +0000125 uint32_t writeDouble(const double dub);
David Reiss4e7530d2007-09-04 21:49:53 +0000126
David Reiss6806fb82010-10-06 17:09:52 +0000127 uint32_t writeString(const std::string& str);
David Reiss4e7530d2007-09-04 21:49:53 +0000128
David Reiss6806fb82010-10-06 17:09:52 +0000129 uint32_t writeBinary(const std::string& str);
David Reissc005b1b2008-02-15 01:38:18 +0000130
David Reiss4e7530d2007-09-04 21:49:53 +0000131 /*
132 * Helper writing functions (don't do state transitions).
133 */
134 inline uint32_t subWriteI32(const int32_t i32);
135
David Reisse67c0e62007-09-07 01:34:12 +0000136 inline uint32_t subWriteString(const std::string& str);
137
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100138 uint32_t subWriteBool(const bool value) { return TBinaryProtocol::writeBool(value); }
David Reiss4e7530d2007-09-04 21:49:53 +0000139
140 /*
141 * Reading functions
142 */
143
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100144 uint32_t readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid);
David Reiss4e7530d2007-09-04 21:49:53 +0000145
146 uint32_t readMessageEnd();
147
148 uint32_t readStructBegin(std::string& name);
149
150 uint32_t readStructEnd();
151
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100152 uint32_t readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId);
David Reiss4e7530d2007-09-04 21:49:53 +0000153
154 uint32_t readFieldEnd();
155
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100156 uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size);
David Reiss4e7530d2007-09-04 21:49:53 +0000157
158 uint32_t readMapEnd();
159
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100160 uint32_t readListBegin(TType& elemType, uint32_t& size);
David Reiss4e7530d2007-09-04 21:49:53 +0000161
162 uint32_t readListEnd();
163
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100164 uint32_t readSetBegin(TType& elemType, uint32_t& size);
David Reiss4e7530d2007-09-04 21:49:53 +0000165
166 uint32_t readSetEnd();
167
168 uint32_t readBool(bool& value);
David Reiss8dfc7322010-10-06 17:09:58 +0000169 // Provide the default readBool() implementation for std::vector<bool>
170 using TVirtualProtocol<TDenseProtocol, TBinaryProtocol>::readBool;
David Reiss4e7530d2007-09-04 21:49:53 +0000171
172 uint32_t readByte(int8_t& byte);
173
174 uint32_t readI16(int16_t& i16);
175
176 uint32_t readI32(int32_t& i32);
177
178 uint32_t readI64(int64_t& i64);
179
180 uint32_t readDouble(double& dub);
181
182 uint32_t readString(std::string& str);
183
David Reissc005b1b2008-02-15 01:38:18 +0000184 uint32_t readBinary(std::string& str);
David Reiss4e7530d2007-09-04 21:49:53 +0000185
186 /*
187 * Helper reading functions (don't do state transitions).
188 */
David Reisse67c0e62007-09-07 01:34:12 +0000189 inline uint32_t subReadI32(int32_t& i32);
190
191 inline uint32_t subReadString(std::string& str);
David Reiss4e7530d2007-09-04 21:49:53 +0000192
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100193 uint32_t subReadBool(bool& value) { return TBinaryProtocol::readBool(value); }
David Reiss4e7530d2007-09-04 21:49:53 +0000194
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100195private:
David Reissce161a92007-09-11 22:09:42 +0000196 // Implementation functions, documented in the .cpp.
David Reiss4e7530d2007-09-04 21:49:53 +0000197 inline void checkTType(const TType ttype);
198 inline void stateTransition();
199
David Reisse67c0e62007-09-07 01:34:12 +0000200 // Read and write variable-length integers.
201 // Uses the same technique as the MIDI file format.
David Reissce161a92007-09-11 22:09:42 +0000202 inline uint32_t vlqRead(uint64_t& vlq);
203 inline uint32_t vlqWrite(uint64_t vlq);
David Reisse67c0e62007-09-07 01:34:12 +0000204
David Reissce161a92007-09-11 22:09:42 +0000205 // Called before throwing an exception to make the object reusable.
206 void resetState() {
207 ts_stack_.clear();
208 idx_stack_.clear();
209 mkv_stack_.clear();
210 }
211
212 // TypeSpec of the top-level structure to write,
213 // for standalone protocol objects.
David Reiss4e7530d2007-09-04 21:49:53 +0000214 TypeSpec* type_spec_;
215
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100216 std::vector<TypeSpec*> ts_stack_; // TypeSpec stack.
217 std::vector<int> idx_stack_; // InDeX stack.
218 std::vector<bool> mkv_stack_; // Map Key/Vlue stack.
219 // True = key, False = value.
David Reiss4e7530d2007-09-04 21:49:53 +0000220
David Reissce161a92007-09-11 22:09:42 +0000221 // True iff this is a standalone instance (no RPC).
222 bool standalone_;
David Reiss4e7530d2007-09-04 21:49:53 +0000223};
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100224}
225}
226} // apache::thrift::protocol
David Reiss4e7530d2007-09-04 21:49:53 +0000227
228#endif // #ifndef _THRIFT_PROTOCOL_TDENSEPROTOCOL_H_