Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <google/protobuf/dynamic_message.h>
- #include <iostream>
- #define FillField(FillFunction, FieldType, CppType) \
- if constexpr (std::is_same_v< \
- google::protobuf::RepeatedField<FieldType>, \
- std::remove_cv_t<std::remove_reference_t<Type>>>) { \
- if (descriptor->cpp_type() == \
- google::protobuf::FieldDescriptor::CppType && \
- descriptor->is_repeated()) { \
- *reflection->MutableRepeatedField<FieldType>(message, descriptor) = \
- std::forward<Type>(value); \
- return; \
- } \
- } else if constexpr (std::is_convertible_v<Type, FieldType>) { \
- if (descriptor->cpp_type() == \
- google::protobuf::FieldDescriptor::CppType && \
- !descriptor->is_repeated()) { \
- reflection->FillFunction(message, descriptor, \
- std::forward<FieldType>(value)); \
- return; \
- } \
- }
- template <typename Type>
- void MakeProto(const google::protobuf::FieldDescriptor *descriptor,
- google::protobuf::Message *message, Type &&value) {
- if constexpr (!std::is_same_v<Type, std::nullptr_t>) {
- auto reflection = message->GetReflection();
- FillField(SetInt32, google::protobuf::int32, CPPTYPE_INT32);
- FillField(SetInt64, google::protobuf::int64, CPPTYPE_INT64);
- FillField(SetUInt32, google::protobuf::uint32, CPPTYPE_UINT32);
- FillField(SetUInt64, google::protobuf::uint64, CPPTYPE_UINT64);
- FillField(SetDouble, double, CPPTYPE_DOUBLE);
- FillField(SetFloat, float, CPPTYPE_FLOAT);
- FillField(SetBool, bool, CPPTYPE_BOOL);
- if constexpr (std::is_enum_v<
- std::remove_cv_t<std::remove_reference_t<Type>>>) {
- FillField(SetEnumValue, int, CPPTYPE_ENUM);
- }
- FillField(SetString, google::protobuf::string, CPPTYPE_STRING);
- if constexpr (std::is_same_v<
- google::protobuf::RepeatedField<
- google::protobuf::Message>,
- std::remove_cv_t<std::remove_reference_t<Type>>>) {
- *reflection->MutableRepeatedField<google::protobuf::Message>(
- message, descriptor) = std::forward<Type>(value);
- return;
- } else if constexpr (std::is_base_of_v<
- google::protobuf::Message,
- std::remove_cv_t<std::remove_reference_t<Type>>>) {
- Type sub_message = std::forward<Type>(value);
- sub_message.GetReflection()->Swap(
- reflection->MutableMessage(message, descriptor), &sub_message);
- return;
- }
- return;
- std::cerr << "error type" << std::endl;
- exit(1);
- }
- }
- template <int I, typename Type>
- inline void MakeProto(google::protobuf::Message *message, Type &&value) {
- MakeProto(message->GetDescriptor()->field(I), message,
- std::forward<Type>(value));
- }
- template <int... Is, typename... Types>
- void MakeProto(std::integer_sequence<int, Is...>,
- google::protobuf::Message *message, std::tuple<Types...> value) {
- (MakeProto<Is>(message,
- std::forward<std::tuple_element_t<Is, decltype(value)>>(
- std::get<Is>(value))),
- ...);
- }
- template <typename Message, typename... Args>
- Message MakeProto(Args &&... args) {
- static_assert(std::is_base_of_v<google::protobuf::Message, Message>,
- "Not a proto message");
- auto descriptor = Message::descriptor();
- Message message;
- if (descriptor->field_count() != sizeof...(Args)) {
- std::cerr << "Not match" << std::endl;
- exit(1);
- }
- MakeProto(std::make_integer_sequence<int, sizeof...(Args)>(), &message,
- std::tuple<Args...>(args...));
- return message;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement