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