22#include <google/protobuf/message.h>
23#include <rapidjson/writer.h>
24#include <rapidjson/reader.h>
25#include <rapidjson/stringbuffer.h>
40 void WriteEnum(google::protobuf::EnumValueDescriptor
const* value) {
_writer.String(value->name()); }
42 void WriteMessage(google::protobuf::Message
const& value);
47 void WriteMessageField(google::protobuf::Message
const& value, google::protobuf::FieldDescriptor
const* field);
48 void WriteSimpleMessageField(google::protobuf::Message
const& value, google::protobuf::FieldDescriptor
const* field);
52 rapidjson::Writer<rapidjson::StringBuffer>
_writer;
57 google::protobuf::Reflection
const* reflection = value.GetReflection();
58 std::vector<google::protobuf::FieldDescriptor const*> fields;
59 reflection->ListFields(value, &fields);
62 for (std::size_t i = 0; i < fields.size(); ++i)
70 _writer.Key(field->name().c_str());
71 if (field->is_repeated())
83 google::protobuf::Reflection
const* reflection = value.GetReflection();
84 switch (field->cpp_type())
86 case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
87 WriteInt32(reflection->GetInt32(value, field));
89 case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
90 WriteInt64(reflection->GetInt64(value, field));
92 case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
95 case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
98 case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
101 case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
102 WriteFloat(reflection->GetFloat(value, field));
104 case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
105 WriteBool(reflection->GetBool(value, field));
107 case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
108 WriteEnum(reflection->GetEnum(value, field));
110 case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
112 std::string strValue = reflection->GetString(value, field);
113 if (field->type() == google::protobuf::FieldDescriptor::TYPE_STRING)
118 for (std::size_t i = 0; i < strValue.length(); ++i)
124 case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
134 google::protobuf::Reflection
const* reflection = value.GetReflection();
135 for (
int32 i = 0; i < reflection->FieldSize(value, field); ++i)
137 switch (field->cpp_type())
139 case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
140 WriteInt32(reflection->GetRepeatedInt32(value, field, i));
142 case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
143 WriteInt64(reflection->GetRepeatedInt64(value, field, i));
145 case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
146 WriteUInt32(reflection->GetRepeatedUInt32(value, field, i));
148 case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
149 WriteUInt64(reflection->GetRepeatedUInt64(value, field, i));
151 case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
152 WriteDouble(reflection->GetRepeatedDouble(value, field, i));
154 case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
155 WriteFloat(reflection->GetRepeatedFloat(value, field, i));
157 case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
158 WriteBool(reflection->GetRepeatedBool(value, field, i));
160 case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
161 WriteEnum(reflection->GetRepeatedEnum(value, field, i));
163 case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
165 std::string strValue = reflection->GetRepeatedString(value, field, i);
166 if (field->type() == google::protobuf::FieldDescriptor::TYPE_STRING)
171 for (std::size_t j = 0; j < strValue.length(); ++j)
177 case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
178 WriteMessage(reflection->GetRepeatedMessage(value, field, i));
186class Deserializer :
public rapidjson::BaseReaderHandler<rapidjson::UTF8<>, Deserializer>
189 bool ReadMessage(std::string
const& json, google::protobuf::Message* message);
191 bool Key(
const Ch* str, rapidjson::SizeType length,
bool copy);
199 bool String(
const Ch* str, rapidjson::SizeType length,
bool copy);
201 bool EndObject(rapidjson::SizeType memberCount);
203 bool EndArray(rapidjson::SizeType memberCount);
208 bool CheckType(google::protobuf::FieldDescriptor::CppType expectedType);
211 std::stack<google::protobuf::FieldDescriptor const*>
_state;
218 rapidjson::StringStream ss(json.c_str());
222 rapidjson::ParseResult result =
_reader.Parse(ss, *
this);
226 return !result.IsError() &&
_errors.empty();
231 google::protobuf::FieldDescriptor
const* field =
_objectState.top()->GetDescriptor()->FindFieldByName(str);
248#define SET_FIELD(message, field, Type, val) do { \
249 if (!field->is_repeated()) \
250 message->GetReflection()->Set ## Type(message, field, val); \
252 message->GetReflection()->Add ## Type(message, field, val); \
258 if (!
CheckType(google::protobuf::FieldDescriptor::CPPTYPE_BOOL))
267 if (!
CheckType(google::protobuf::FieldDescriptor::CPPTYPE_INT32))
276 google::protobuf::FieldDescriptor
const* field =
_state.top();
277 google::protobuf::Message* message =
_objectState.top();
278 switch (field->cpp_type())
280 case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
283 case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
285 if (field->type() != google::protobuf::FieldDescriptor::TYPE_BYTES)
287 _errors.emplace_back(
"Expected field type to be bytes but got string instead.");
290 std::string currentValue = message->GetReflection()->GetString(*message, field);
291 currentValue.append(1, (
char)i);
292 message->GetReflection()->SetString(message, field, currentValue);
305 if (!
CheckType(google::protobuf::FieldDescriptor::CPPTYPE_INT64))
314 if (!
CheckType(google::protobuf::FieldDescriptor::CPPTYPE_UINT64))
323 google::protobuf::FieldDescriptor
const* field =
_state.top();
324 google::protobuf::Message* message =
_objectState.top();
325 switch (field->cpp_type())
327 case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
330 case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
343 google::protobuf::FieldDescriptor
const* field =
_state.top();
344 google::protobuf::Message* message =
_objectState.top();
345 switch (field->cpp_type())
347 case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
349 google::protobuf::EnumValueDescriptor
const* enumValue = field->enum_type()->FindValueByName(str);
352 _errors.push_back(
Trinity::StringFormat(
"Field {} enum {} does not have a value named {}.", field->full_name(), field->enum_type()->full_name(), str));
356 SET_FIELD(message, field, Enum, enumValue);
359 case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
375 if (
_state.top()->cpp_type() != google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE)
381 google::protobuf::Message* containingMessage =
_objectState.top();
382 if (!
_state.top()->is_repeated())
383 _objectState.push(containingMessage->GetReflection()->MutableMessage(containingMessage,
_state.top()));
385 _objectState.push(containingMessage->GetReflection()->AddMessage(containingMessage,
_state.top()));
406 _errors.emplace_back(
"Root cannot be an array.");
410 if (
_state.top()->is_repeated() ^ (
_state.top()->type() != google::protobuf::FieldDescriptor::TYPE_BYTES))
421 if (
_state.top()->cpp_type() != expectedType)
424 _state.top()->full_name(), google::protobuf::FieldDescriptor::CppTypeName(expectedType),
_state.top()->cpp_type_name()));
451 for (std::size_t i = 0; i < deserializer.
GetErrors().
size(); ++i)
#define TC_LOG_ERROR(filterType__,...)
#define SET_FIELD(message, field, Type, val)
std::stack< google::protobuf::FieldDescriptor const * > _state
bool CheckType(google::protobuf::FieldDescriptor::CppType expectedType)
bool EndArray(rapidjson::SizeType memberCount)
std::vector< std::string > const & GetErrors() const
bool ReadMessage(std::string const &json, google::protobuf::Message *message)
std::vector< std::string > _errors
bool String(const Ch *str, rapidjson::SizeType length, bool copy)
rapidjson::Reader _reader
bool EndObject(rapidjson::SizeType memberCount)
std::stack< google::protobuf::Message * > _objectState
bool Key(const Ch *str, rapidjson::SizeType length, bool copy)
void WriteMessage(google::protobuf::Message const &value)
void WriteUInt32(uint32 value)
std::string GetString() const
void WriteSimpleMessageField(google::protobuf::Message const &value, google::protobuf::FieldDescriptor const *field)
void WriteBool(bool value)
void WriteString(std::string const &value)
void WriteMessageField(google::protobuf::Message const &value, google::protobuf::FieldDescriptor const *field)
void WriteEnum(google::protobuf::EnumValueDescriptor const *value)
void WriteFloat(float value)
rapidjson::Writer< rapidjson::StringBuffer > _writer
void WriteInt64(int64 value)
void WriteDouble(double value)
void WriteRepeatedMessageField(google::protobuf::Message const &value, google::protobuf::FieldDescriptor const *field)
rapidjson::StringBuffer _buffer
void WriteInt32(int32 value)
void WriteUInt64(uint64 value)
TC_SHARED_API bool Deserialize(std::string const &json, google::protobuf::Message *message)
TC_SHARED_API std::string Serialize(google::protobuf::Message const &message)
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
constexpr std::size_t size()