1 /*
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef THRIFT2_PROTOCOL_TSIMPLEJSONPROTOCOL_TCC_
18 #define THRIFT2_PROTOCOL_TSIMPLEJSONPROTOCOL_TCC_ 1
19
20 #include <thrift/lib/cpp2/protocol/SimpleJSONProtocol.h>
21
22 #include <limits>
23 #include <string>
24
25 #include <folly/Conv.h>
26 #include <folly/dynamic.h>
27 #include <folly/json.h>
28 #include <thrift/lib/cpp/protocol/TBase64Utils.h>
29
30 namespace apache {
31 namespace thrift {
32
33 /*
34 * Public writing methods
35 */
writeStructBegin(const char *)36 uint32_t SimpleJSONProtocolWriter::writeStructBegin(const char* /*name*/) {
37 auto ret = writeContext();
38 return ret + beginContext(ContextType::MAP);
39 }
40
writeStructEnd()41 uint32_t SimpleJSONProtocolWriter::writeStructEnd() {
42 return endContext();
43 }
44
writeFieldBegin(const char * name,TType,int16_t)45 uint32_t SimpleJSONProtocolWriter::writeFieldBegin(
46 const char* name, TType /*fieldType*/, int16_t /*fieldId*/) {
47 auto ret = writeContext();
48 return ret + writeJSONString(name);
49 }
50
writeFieldEnd()51 uint32_t SimpleJSONProtocolWriter::writeFieldEnd() {
52 return 0;
53 }
54
writeFieldStop()55 uint32_t SimpleJSONProtocolWriter::writeFieldStop() {
56 return 0;
57 }
58
writeMapBegin(const TType,TType,uint32_t)59 uint32_t SimpleJSONProtocolWriter::writeMapBegin(
60 const TType /*keyType*/, TType /*valType*/, uint32_t /*size*/) {
61 auto ret = writeContext();
62 return ret + beginContext(ContextType::MAP);
63 }
64
writeMapEnd()65 uint32_t SimpleJSONProtocolWriter::writeMapEnd() {
66 return endContext();
67 }
68
writeListBegin(TType,uint32_t)69 uint32_t SimpleJSONProtocolWriter::writeListBegin(
70 TType /*elemType*/, uint32_t /*size*/) {
71 auto ret = writeContext();
72 return ret + beginContext(ContextType::ARRAY);
73 }
74
writeListEnd()75 uint32_t SimpleJSONProtocolWriter::writeListEnd() {
76 return endContext();
77 }
78
writeSetBegin(TType,uint32_t)79 uint32_t SimpleJSONProtocolWriter::writeSetBegin(
80 TType /*elemType*/, uint32_t /*size*/) {
81 auto ret = writeContext();
82 return ret + beginContext(ContextType::ARRAY);
83 }
84
writeSetEnd()85 uint32_t SimpleJSONProtocolWriter::writeSetEnd() {
86 return endContext();
87 }
88
writeBool(bool value)89 uint32_t SimpleJSONProtocolWriter::writeBool(bool value) {
90 auto ret = writeContext();
91 return ret + writeJSONBool(value);
92 }
93
94 /**
95 * Functions that return the serialized size
96 */
97
serializedMessageSize(const std::string & name)98 uint32_t SimpleJSONProtocolWriter::serializedMessageSize(
99 const std::string& name) const {
100 return 2 // list begin and end
101 + serializedSizeI32() * 3 + serializedSizeString(name);
102 }
103
serializedFieldSize(const char * name,TType,int16_t)104 uint32_t SimpleJSONProtocolWriter::serializedFieldSize(
105 const char* name, TType /*fieldType*/, int16_t /*fieldId*/) const {
106 // string plus ":"
107 return static_cast<uint32_t>(strlen(name)) * 6 + 3;
108 }
109
serializedStructSize(const char *)110 uint32_t SimpleJSONProtocolWriter::serializedStructSize(
111 const char* /*name*/) const {
112 return 2; // braces
113 }
114
serializedSizeMapBegin(TType,TType,uint32_t)115 uint32_t SimpleJSONProtocolWriter::serializedSizeMapBegin(
116 TType /*keyType*/, TType /*valType*/, uint32_t /*size*/) const {
117 return 1;
118 }
119
serializedSizeMapEnd()120 uint32_t SimpleJSONProtocolWriter::serializedSizeMapEnd() const {
121 return 1;
122 }
123
serializedSizeListBegin(TType,uint32_t)124 uint32_t SimpleJSONProtocolWriter::serializedSizeListBegin(
125 TType /*elemType*/, uint32_t /*size*/) const {
126 return 1;
127 }
128
serializedSizeListEnd()129 uint32_t SimpleJSONProtocolWriter::serializedSizeListEnd() const {
130 return 1;
131 }
132
serializedSizeSetBegin(TType,uint32_t)133 uint32_t SimpleJSONProtocolWriter::serializedSizeSetBegin(
134 TType /*elemType*/, uint32_t /*size*/) const {
135 return 1;
136 }
137
serializedSizeSetEnd()138 uint32_t SimpleJSONProtocolWriter::serializedSizeSetEnd() const {
139 return 1;
140 }
141
serializedSizeStop()142 uint32_t SimpleJSONProtocolWriter::serializedSizeStop() const {
143 return 0;
144 }
145
serializedSizeBool(bool)146 uint32_t SimpleJSONProtocolWriter::serializedSizeBool(bool /*val*/) const {
147 return 6;
148 }
149
150 /**
151 * Protected reading functions
152 */
153
154 /**
155 * Public reading functions
156 */
157
readStructBegin(std::string &)158 void SimpleJSONProtocolReader::readStructBegin(std::string& /*name*/) {
159 ensureAndBeginContext(ContextType::MAP);
160 }
161
readStructEnd()162 void SimpleJSONProtocolReader::readStructEnd() {
163 endContext();
164 }
165
readFieldBegin(std::string & name,TType & fieldType,int16_t & fieldId)166 void SimpleJSONProtocolReader::readFieldBegin(
167 std::string& name, TType& fieldType, int16_t& fieldId) {
168 if (!peekMap()) {
169 fieldType = TType::T_STOP;
170 fieldId = 0;
171 return;
172 }
173 fieldId = std::numeric_limits<int16_t>::min();
174 fieldType = TType::T_VOID;
175 readString(name);
176 ensureAndSkipContext();
177 skipWhitespace();
178 auto peek = peekCharSafe();
179 if (peek == 'n') {
180 bool tmp;
181 ensureAndReadContext(tmp);
182 readWhitespace();
183 readJSONNull();
184 readFieldBegin(name, fieldType, fieldId);
185 }
186 }
187
readFieldEnd()188 void SimpleJSONProtocolReader::readFieldEnd() {}
189
readMapBegin(TType &,TType &,uint32_t & size)190 void SimpleJSONProtocolReader::readMapBegin(
191 TType& /*keyType*/, TType& /*valType*/, uint32_t& size) {
192 size = std::numeric_limits<uint32_t>::max();
193 ensureAndBeginContext(ContextType::MAP);
194 }
195
readMapEnd()196 void SimpleJSONProtocolReader::readMapEnd() {
197 endContext();
198 }
199
readListBegin(TType &,uint32_t & size)200 void SimpleJSONProtocolReader::readListBegin(
201 TType& /*elemType*/, uint32_t& size) {
202 size = std::numeric_limits<uint32_t>::max();
203 ensureAndBeginContext(ContextType::ARRAY);
204 }
205
readListEnd()206 void SimpleJSONProtocolReader::readListEnd() {
207 endContext();
208 }
209
readSetBegin(TType &,uint32_t & size)210 void SimpleJSONProtocolReader::readSetBegin(
211 TType& /*elemType*/, uint32_t& size) {
212 size = std::numeric_limits<uint32_t>::max();
213 ensureAndBeginContext(ContextType::ARRAY);
214 }
215
readSetEnd()216 void SimpleJSONProtocolReader::readSetEnd() {
217 endContext();
218 }
219
readBool(bool & value)220 void SimpleJSONProtocolReader::readBool(bool& value) {
221 readInContext<bool>(value);
222 }
223
readBool(std::vector<bool>::reference value)224 void SimpleJSONProtocolReader::readBool(std::vector<bool>::reference value) {
225 bool tmp = false;
226 readInContext<bool>(tmp);
227 value = tmp;
228 }
229
peekMap()230 bool SimpleJSONProtocolReader::peekMap() {
231 skipWhitespace();
232 return peekCharSafe() != apache::thrift::detail::json::kJSONObjectEnd;
233 }
234
peekList()235 bool SimpleJSONProtocolReader::peekList() {
236 skipWhitespace();
237 return peekCharSafe() != apache::thrift::detail::json::kJSONArrayEnd;
238 }
239
peekSet()240 bool SimpleJSONProtocolReader::peekSet() {
241 return peekList();
242 }
243
skip(TType)244 void SimpleJSONProtocolReader::skip(TType /*type*/) {
245 bool keyish;
246 ensureAndReadContext(keyish);
247 readWhitespace();
248 auto ch = peekCharSafe();
249 if (ch == apache::thrift::detail::json::kJSONObjectStart) {
250 beginContext(ContextType::MAP);
251 while (true) {
252 skipWhitespace();
253 if (peekCharSafe() == apache::thrift::detail::json::kJSONObjectEnd) {
254 break;
255 }
256 skip(TType::T_VOID);
257 skip(TType::T_VOID);
258 }
259 endContext();
260 } else if (ch == apache::thrift::detail::json::kJSONArrayStart) {
261 beginContext(ContextType::ARRAY);
262 while (true) {
263 skipWhitespace();
264 if (peekCharSafe() == apache::thrift::detail::json::kJSONArrayEnd) {
265 break;
266 }
267 skip(TType::T_VOID);
268 }
269 endContext();
270 } else if (ch == apache::thrift::detail::json::kJSONStringDelimiter) {
271 std::string tmp;
272 readJSONVal(tmp);
273 } else if (ch == '-' || ch == '+' || (ch >= '0' && ch <= '9')) {
274 double tmp;
275 readJSONVal(tmp);
276 } else if (ch == 't' || ch == 'f') {
277 bool tmp;
278 readJSONVal(tmp);
279 } else if (ch == 'n') {
280 readJSONNull();
281 } else {
282 throwInvalidFieldStart(ch);
283 }
284 }
285
286 } // namespace thrift
287 } // namespace apache
288
289 #endif // #ifndef THRIFT2_PROTOCOL_TSIMPLEJSONPROTOCOL_TCC_
290