Advertisement
Guest User

Untitled

a guest
Jun 26th, 2019
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.17 KB | None | 0 0
  1. #include <google/protobuf/dynamic_message.h>
  2. #include <iostream>
  3. #define FillField(FillFunction, FieldType, CppType) \
  4. if constexpr (std::is_same_v< \
  5. google::protobuf::RepeatedField<FieldType>, \
  6. std::remove_cv_t<std::remove_reference_t<Type>>>) { \
  7. if (descriptor->cpp_type() == \
  8. google::protobuf::FieldDescriptor::CppType && \
  9. descriptor->is_repeated()) { \
  10. *reflection->MutableRepeatedField<FieldType>(message, descriptor) = \
  11. std::forward<Type>(value); \
  12. return; \
  13. } \
  14. } else if constexpr (std::is_convertible_v<Type, FieldType>) { \
  15. if (descriptor->cpp_type() == \
  16. google::protobuf::FieldDescriptor::CppType && \
  17. !descriptor->is_repeated()) { \
  18. reflection->FillFunction(message, descriptor, \
  19. std::forward<FieldType>(value)); \
  20. return; \
  21. } \
  22. }
  23.  
  24. template <typename Type>
  25. void MakeProto(const google::protobuf::FieldDescriptor *descriptor,
  26. google::protobuf::Message *message, Type &&value) {
  27. if constexpr (!std::is_same_v<Type, std::nullptr_t>) {
  28. auto reflection = message->GetReflection();
  29.  
  30. FillField(SetInt32, google::protobuf::int32, CPPTYPE_INT32);
  31. FillField(SetInt64, google::protobuf::int64, CPPTYPE_INT64);
  32. FillField(SetUInt32, google::protobuf::uint32, CPPTYPE_UINT32);
  33. FillField(SetUInt64, google::protobuf::uint64, CPPTYPE_UINT64);
  34. FillField(SetDouble, double, CPPTYPE_DOUBLE);
  35. FillField(SetFloat, float, CPPTYPE_FLOAT);
  36. FillField(SetBool, bool, CPPTYPE_BOOL);
  37. if constexpr (std::is_enum_v<
  38. std::remove_cv_t<std::remove_reference_t<Type>>>) {
  39. FillField(SetEnumValue, int, CPPTYPE_ENUM);
  40. }
  41. FillField(SetString, google::protobuf::string, CPPTYPE_STRING);
  42. if constexpr (std::is_same_v<
  43. google::protobuf::RepeatedField<
  44. google::protobuf::Message>,
  45. std::remove_cv_t<std::remove_reference_t<Type>>>) {
  46. *reflection->MutableRepeatedField<google::protobuf::Message>(
  47. message, descriptor) = std::forward<Type>(value);
  48. return;
  49. } else if constexpr (std::is_base_of_v<
  50. google::protobuf::Message,
  51. std::remove_cv_t<std::remove_reference_t<Type>>>) {
  52. Type sub_message = std::forward<Type>(value);
  53. sub_message.GetReflection()->Swap(
  54. reflection->MutableMessage(message, descriptor), &sub_message);
  55. return;
  56. }
  57.  
  58. return;
  59.  
  60. std::cerr << "error type" << std::endl;
  61. exit(1);
  62. }
  63. }
  64.  
  65. template <int I, typename Type>
  66. inline void MakeProto(google::protobuf::Message *message, Type &&value) {
  67. MakeProto(message->GetDescriptor()->field(I), message,
  68. std::forward<Type>(value));
  69. }
  70.  
  71. template <int... Is, typename... Types>
  72. void MakeProto(std::integer_sequence<int, Is...>,
  73. google::protobuf::Message *message, std::tuple<Types...> value) {
  74. (MakeProto<Is>(message,
  75. std::forward<std::tuple_element_t<Is, decltype(value)>>(
  76. std::get<Is>(value))),
  77. ...);
  78. }
  79.  
  80. template <typename Message, typename... Args>
  81. Message MakeProto(Args &&... args) {
  82. static_assert(std::is_base_of_v<google::protobuf::Message, Message>,
  83. "Not a proto message");
  84. auto descriptor = Message::descriptor();
  85. Message message;
  86. if (descriptor->field_count() != sizeof...(Args)) {
  87. std::cerr << "Not match" << std::endl;
  88. exit(1);
  89. }
  90.  
  91. MakeProto(std::make_integer_sequence<int, sizeof...(Args)>(), &message,
  92. std::tuple<Args...>(args...));
  93.  
  94. return message;
  95. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement