| #ifndef GOOGLE_PROTOBUF_REFLECTION_VISIT_FIELD_INFO_H__ |
| #define GOOGLE_PROTOBUF_REFLECTION_VISIT_FIELD_INFO_H__ |
| |
| #include <cstddef> |
| #include <cstdint> |
| #include <iterator> |
| #include <string> |
| #include <type_traits> |
| #include <utility> |
| |
| #include "absl/log/absl_check.h" |
| #include "absl/strings/cord.h" |
| #include "absl/strings/string_view.h" |
| #include "google/protobuf/arenastring.h" |
| #include "google/protobuf/descriptor.h" |
| #include "google/protobuf/descriptor.pb.h" |
| #include "google/protobuf/extension_set.h" |
| #include "google/protobuf/inlined_string_field.h" |
| #include "google/protobuf/map_field.h" |
| #include "google/protobuf/message.h" |
| #include "google/protobuf/port.h" |
| #include "google/protobuf/wire_format_lite.h" |
| |
| |
| // clang-format off |
| #include "google/protobuf/port_def.inc" |
| // clang-format on |
| |
| namespace google { |
| namespace protobuf { |
| namespace internal { |
| |
| // A range adaptor for a pair of iterators. |
| // |
| // This just wraps two iterators into a range-compatible interface. Nothing |
| // fancy at all. |
| template <typename IteratorT> |
| class iterator_range { |
| public: |
| using iterator = IteratorT; |
| using const_iterator = IteratorT; |
| using value_type = typename std::iterator_traits<IteratorT>::value_type; |
| |
| iterator_range() : begin_iterator_(), end_iterator_() {} |
| iterator_range(IteratorT begin_iterator, IteratorT end_iterator) |
| : begin_iterator_(std::move(begin_iterator)), |
| end_iterator_(std::move(end_iterator)) {} |
| |
| IteratorT begin() const { return begin_iterator_; } |
| IteratorT end() const { return end_iterator_; } |
| |
| // Returns the size of the wrapped range. Does not participate in overload |
| // resolution for non-random-access iterators, since in those cases this is a |
| // slow operation (it must walk the entire range and maintain a count). |
| // |
| // Users who need to know the "size" of a non-random-access iterator_range |
| // should pass the range to `absl::c_distance()` instead. |
| template <class It = IteratorT> |
| typename std::enable_if<std::is_base_of<std::random_access_iterator_tag, |
| typename std::iterator_traits< |
| It>::iterator_category>::value, |
| size_t>::type |
| size() const { |
| return std::distance(begin_iterator_, end_iterator_); |
| } |
| // Returns true if this iterator range refers to an empty sequence, and false |
| // otherwise. |
| bool empty() const { return begin_iterator_ == end_iterator_; } |
| |
| private: |
| IteratorT begin_iterator_, end_iterator_; |
| }; |
| |
| #ifdef __cpp_if_constexpr |
| |
| |
| template <bool is_oneof> |
| struct DynamicFieldInfoHelper { |
| template <typename T> |
| static T Get(const Reflection* reflection, const Message& message, |
| const FieldDescriptor* field) { |
| if constexpr (is_oneof) { |
| return reflection->GetRaw<T>(message, field); |
| } else { |
| return reflection->GetRawNonOneof<T>(message, field); |
| } |
| } |
| template <typename T> |
| static T& GetRef(const Reflection* reflection, const Message& message, |
| const FieldDescriptor* field) { |
| if constexpr (is_oneof) { |
| return reflection->GetRaw<T>(message, field); |
| } else { |
| return reflection->GetRawNonOneof<T>(message, field); |
| } |
| } |
| template <typename T> |
| static T& Mutable(const Reflection* reflection, Message& message, |
| const FieldDescriptor* field) { |
| if constexpr (is_oneof) { |
| return *reflection->MutableRaw<T>(&message, field); |
| } else { |
| return *reflection->MutableRawNonOneof<T>(&message, field); |
| } |
| } |
| |
| static void ClearField(const Reflection* reflection, Message& message, |
| const FieldDescriptor* field) { |
| if constexpr (is_oneof) { |
| reflection->ClearOneofField(&message, field); |
| } else { |
| reflection->ClearField(&message, field); |
| } |
| } |
| |
| static absl::string_view GetStringView(const Reflection* reflection, |
| const Message& message, |
| const FieldDescriptor* field) { |
| auto ctype = cpp::EffectiveStringCType(field); |
| ABSL_DCHECK_NE(ctype, FieldOptions::CORD); |
| ABSL_DCHECK(!is_oneof || reflection->HasOneofField(message, field)); |
| auto str = Get<ArenaStringPtr>(reflection, message, field); |
| ABSL_DCHECK(!str.IsDefault()); |
| return str.Get(); |
| } |
| }; |
| |
| struct DynamicExtensionInfoHelper { |
| using Extension = ExtensionSet::Extension; |
| |
| #define PROTOBUF_SINGULAR_PRIMITIVE_METHOD(NAME, FIELD_TYPE, VAR) \ |
| static FIELD_TYPE Get##NAME(const Extension& ext) { \ |
| return ext.VAR##_value; \ |
| } \ |
| static void Set##NAME(Extension& ext, FIELD_TYPE value) { \ |
| ext.VAR##_value = value; \ |
| } \ |
| static void Clear##NAME(Extension& ext) { ext.is_cleared = true; } |
| |
| PROTOBUF_SINGULAR_PRIMITIVE_METHOD(Int32, int32_t, int32_t); |
| PROTOBUF_SINGULAR_PRIMITIVE_METHOD(Int64, int64_t, int64_t); |
| PROTOBUF_SINGULAR_PRIMITIVE_METHOD(UInt32, uint32_t, uint32_t); |
| PROTOBUF_SINGULAR_PRIMITIVE_METHOD(UInt64, uint64_t, uint64_t); |
| PROTOBUF_SINGULAR_PRIMITIVE_METHOD(Float, float, float); |
| PROTOBUF_SINGULAR_PRIMITIVE_METHOD(Double, double, double); |
| PROTOBUF_SINGULAR_PRIMITIVE_METHOD(Bool, bool, bool); |
| PROTOBUF_SINGULAR_PRIMITIVE_METHOD(Enum, int, enum); |
| |
| #undef PROTOBUF_SINGULAR_PRIMITIVE_METHOD |
| |
| #define PROTOBUF_REPEATED_FIELD_METHODS(NAME, FIELD_TYPE, VAR) \ |
| static const RepeatedField<FIELD_TYPE>* GetRepeated##NAME( \ |
| const Extension& ext) { \ |
| return ext.repeated_##VAR##_value; \ |
| } \ |
| static RepeatedField<FIELD_TYPE>* MutableRepeated##NAME(Extension& ext) { \ |
| return ext.repeated_##VAR##_value; \ |
| } \ |
| static void ClearRepeated##NAME(Extension& ext) { \ |
| return ext.repeated_##VAR##_value->Clear(); \ |
| } |
| |
| PROTOBUF_REPEATED_FIELD_METHODS(Int32, int32_t, int32_t); |
| PROTOBUF_REPEATED_FIELD_METHODS(Int64, int64_t, int64_t); |
| PROTOBUF_REPEATED_FIELD_METHODS(UInt32, uint32_t, uint32_t); |
| PROTOBUF_REPEATED_FIELD_METHODS(UInt64, uint64_t, uint64_t); |
| PROTOBUF_REPEATED_FIELD_METHODS(Float, float, float); |
| PROTOBUF_REPEATED_FIELD_METHODS(Double, double, double); |
| PROTOBUF_REPEATED_FIELD_METHODS(Bool, bool, bool); |
| PROTOBUF_REPEATED_FIELD_METHODS(Enum, int, enum); |
| |
| #undef PROTOBUF_REPEATED_FIELD_METHODS |
| |
| #define PROTOBUF_REPEATED_PTR_FIELD_METHODS(FIELD_TYPE, NAME, VAR) \ |
| static const RepeatedPtrField<FIELD_TYPE>* GetRepeated##NAME( \ |
| const Extension& ext) { \ |
| return ext.repeated_##VAR##_value; \ |
| } \ |
| static RepeatedPtrField<FIELD_TYPE>* MutableRepeated##NAME(Extension& ext) { \ |
| return ext.repeated_##VAR##_value; \ |
| } \ |
| static void ClearRepeated##NAME(Extension& ext) { \ |
| return ext.repeated_##VAR##_value->Clear(); \ |
| } |
| |
| PROTOBUF_REPEATED_PTR_FIELD_METHODS(std::string, String, string); |
| PROTOBUF_REPEATED_PTR_FIELD_METHODS(MessageLite, Message, message); |
| |
| #undef PROTOBUF_REPEATED_PTR_FIELD_METHODS |
| |
| static absl::string_view GetStringView(const Extension& ext) { |
| return *ext.string_value; |
| } |
| static void SetStringView(Extension& ext, absl::string_view value) { |
| ext.string_value->assign(value.data(), value.size()); |
| } |
| static void ClearStringView(Extension& ext) { |
| ext.is_cleared = true; |
| ext.string_value->clear(); |
| } |
| |
| static const Message& GetMessage(const Extension& ext) { |
| return DownCast<const Message&>(*ext.message_value); |
| } |
| static Message& MutableMessage(Extension& ext) { |
| return DownCast<Message&>(*ext.message_value); |
| } |
| static void ClearMessage(Extension& ext) { |
| ext.is_cleared = true; |
| ext.message_value->Clear(); |
| } |
| |
| static const Message& GetLazyMessage(const Extension& ext, |
| const Message& prototype, Arena* arena) { |
| return DownCast<const Message&>( |
| ext.lazymessage_value->GetMessage(prototype, arena)); |
| } |
| static const Message& GetLazyMessageIgnoreUnparsed(const Extension& ext, |
| const Message& prototype, |
| Arena* arena) { |
| return DownCast<const Message&>( |
| ext.lazymessage_value->GetMessageIgnoreUnparsed(prototype, arena)); |
| } |
| static Message& MutableLazyMessage(Extension& ext, const Message& prototype, |
| Arena* arena) { |
| return DownCast<Message&>( |
| *ext.lazymessage_value->MutableMessage(prototype, arena)); |
| } |
| static void ClearLazyMessage(Extension& ext) { |
| ext.is_cleared = true; |
| return ext.lazymessage_value->Clear(); |
| } |
| static size_t ByteSizeLongLazyMessage(const Extension& ext) { |
| return ext.lazymessage_value->ByteSizeLong(); |
| } |
| }; |
| |
| //////////////////////////////////////////////////////////////////////// |
| // Primitive fields |
| //////////////////////////////////////////////////////////////////////// |
| template <typename MessageT, typename FieldT, |
| FieldDescriptor::CppType cpp_type_parameter, bool is_oneof_parameter> |
| struct SingularPrimitive { |
| constexpr SingularPrimitive(const Reflection* r, MessageT& m, |
| const FieldDescriptor* f) |
| : reflection(r), message(m), field(f) {} |
| |
| int number() const { return field->number(); } |
| FieldDescriptor::Type type() const { return field->type(); } |
| |
| FieldT Get() const { |
| return DynamicFieldInfoHelper<is_oneof>::template Get<FieldT>( |
| reflection, message, field); |
| } |
| void Set(FieldT value) { |
| DynamicFieldInfoHelper<is_oneof>::template Mutable<FieldT>( |
| reflection, message, field) = value; |
| } |
| void Clear() { |
| DynamicFieldInfoHelper<is_oneof>::ClearField(reflection, message, field); |
| } |
| |
| static constexpr FieldDescriptor::CppType cpp_type = // NOLINT |
| cpp_type_parameter; |
| static constexpr bool is_repeated = false; // NOLINT |
| static constexpr bool is_map = false; // NOLINT |
| static constexpr bool is_extension = false; // NOLINT |
| static constexpr bool is_oneof = is_oneof_parameter; // NOLINT |
| |
| const Reflection* reflection; |
| MessageT& message; |
| const FieldDescriptor* field; |
| }; |
| |
| #define PROTOBUF_DYN_FIELD_INFO_VARINT(NAME, CPPTYPE, FIELD_TYPE) \ |
| template <typename MessageT, bool is_oneof> \ |
| struct NAME##DynamicFieldInfo \ |
| : SingularPrimitive<MessageT, FIELD_TYPE, \ |
| FieldDescriptor::CPPTYPE_##CPPTYPE, is_oneof> { \ |
| using BaseT = \ |
| SingularPrimitive<MessageT, FIELD_TYPE, \ |
| FieldDescriptor::CPPTYPE_##CPPTYPE, is_oneof>; \ |
| \ |
| constexpr NAME##DynamicFieldInfo(const Reflection* r, MessageT& m, \ |
| const FieldDescriptor* f) \ |
| : BaseT(r, m, f) {} \ |
| size_t FieldByteSize() const { \ |
| return WireFormatLite::NAME##Size(BaseT::Get()); \ |
| } \ |
| }; |
| |
| #define PROTOBUF_DYN_FIELD_INFO_FIXED(NAME, CPPTYPE, FIELD_TYPE) \ |
| template <typename MessageT, bool is_oneof> \ |
| struct NAME##DynamicFieldInfo \ |
| : SingularPrimitive<MessageT, FIELD_TYPE, \ |
| FieldDescriptor::CPPTYPE_##CPPTYPE, is_oneof> { \ |
| using BaseT = \ |
| SingularPrimitive<MessageT, FIELD_TYPE, \ |
| FieldDescriptor::CPPTYPE_##CPPTYPE, is_oneof>; \ |
| \ |
| constexpr NAME##DynamicFieldInfo(const Reflection* r, MessageT& m, \ |
| const FieldDescriptor* f) \ |
| : BaseT(r, m, f) {} \ |
| constexpr size_t FieldByteSize() const { \ |
| return WireFormatLite::k##NAME##Size; \ |
| } \ |
| }; |
| |
| PROTOBUF_DYN_FIELD_INFO_VARINT(Int32, INT32, int32_t); |
| PROTOBUF_DYN_FIELD_INFO_VARINT(Int64, INT64, int64_t); |
| PROTOBUF_DYN_FIELD_INFO_VARINT(UInt32, UINT32, uint32_t); |
| PROTOBUF_DYN_FIELD_INFO_VARINT(UInt64, UINT64, uint64_t); |
| PROTOBUF_DYN_FIELD_INFO_VARINT(SInt32, INT32, int32_t); |
| PROTOBUF_DYN_FIELD_INFO_VARINT(SInt64, INT64, int64_t); |
| |
| PROTOBUF_DYN_FIELD_INFO_FIXED(Fixed32, UINT32, uint32_t); |
| PROTOBUF_DYN_FIELD_INFO_FIXED(Fixed64, UINT64, uint64_t); |
| PROTOBUF_DYN_FIELD_INFO_FIXED(SFixed32, INT32, int32_t); |
| PROTOBUF_DYN_FIELD_INFO_FIXED(SFixed64, INT64, int64_t); |
| PROTOBUF_DYN_FIELD_INFO_FIXED(Double, DOUBLE, double); |
| PROTOBUF_DYN_FIELD_INFO_FIXED(Float, FLOAT, float); |
| PROTOBUF_DYN_FIELD_INFO_FIXED(Bool, BOOL, bool); |
| |
| #undef PROTOBUF_DYN_FIELD_INFO_VARINT |
| #undef PROTOBUF_DYN_FIELD_INFO_FIXED |
| |
| //////////////////////////////////////////////////////////////////////// |
| // Extension primitive fields |
| //////////////////////////////////////////////////////////////////////// |
| #define PROTOBUF_DYN_EXTENSION_INFO_VARINT(NAME, CPPNAME, CPPTYPE, FIELD_TYPE) \ |
| template <typename ExtensionT> \ |
| struct NAME##DynamicExtensionInfo { \ |
| constexpr NAME##DynamicExtensionInfo(ExtensionT& e, int n) \ |
| : ext(e), ext_number(n) {} \ |
| int number() const { return ext_number; } \ |
| FieldDescriptor::Type type() const { \ |
| return static_cast<FieldDescriptor::Type>(ext.type); \ |
| } \ |
| FIELD_TYPE Get() const { \ |
| return DynamicExtensionInfoHelper::Get##CPPNAME(ext); \ |
| } \ |
| void Set(FIELD_TYPE value) { \ |
| DynamicExtensionInfoHelper::Set##CPPNAME(ext, value); \ |
| } \ |
| void Clear() { DynamicExtensionInfoHelper::Clear##CPPNAME(ext); } \ |
| size_t FieldByteSize() const { return WireFormatLite::NAME##Size(Get()); } \ |
| \ |
| static constexpr FieldDescriptor::CppType cpp_type = \ |
| FieldDescriptor::CPPTYPE_##CPPTYPE; \ |
| static constexpr bool is_repeated = false; \ |
| static constexpr bool is_map = false; \ |
| static constexpr bool is_extension = true; \ |
| static constexpr bool is_oneof = false; \ |
| \ |
| ExtensionT& ext; \ |
| int ext_number; \ |
| }; |
| |
| #define PROTOBUF_DYN_EXTENSION_INFO_FIXED(NAME, CPPNAME, CPPTYPE, FIELD_TYPE) \ |
| template <typename ExtensionT> \ |
| struct NAME##DynamicExtensionInfo { \ |
| constexpr NAME##DynamicExtensionInfo(ExtensionT& e, int n) \ |
| : ext(e), ext_number(n) {} \ |
| int number() const { return ext_number; } \ |
| FieldDescriptor::Type type() const { \ |
| return static_cast<FieldDescriptor::Type>(ext.type); \ |
| } \ |
| FIELD_TYPE Get() const { \ |
| return DynamicExtensionInfoHelper::Get##CPPNAME(ext); \ |
| } \ |
| void Set(FIELD_TYPE value) { \ |
| DynamicExtensionInfoHelper::Set##CPPNAME(ext, value); \ |
| } \ |
| void Clear() { DynamicExtensionInfoHelper::Clear##CPPNAME(ext); } \ |
| constexpr size_t FieldByteSize() const { \ |
| return WireFormatLite::k##NAME##Size; \ |
| } \ |
| \ |
| static constexpr FieldDescriptor::CppType cpp_type = \ |
| FieldDescriptor::CPPTYPE_##CPPTYPE; \ |
| static constexpr bool is_repeated = false; \ |
| static constexpr bool is_map = false; \ |
| static constexpr bool is_extension = true; \ |
| static constexpr bool is_oneof = false; \ |
| \ |
| ExtensionT& ext; \ |
| int ext_number; \ |
| }; |
| |
| PROTOBUF_DYN_EXTENSION_INFO_VARINT(Int32, Int32, INT32, int32_t); |
| PROTOBUF_DYN_EXTENSION_INFO_VARINT(Int64, Int64, INT64, int64_t); |
| PROTOBUF_DYN_EXTENSION_INFO_VARINT(UInt32, UInt32, UINT32, uint32_t); |
| PROTOBUF_DYN_EXTENSION_INFO_VARINT(UInt64, UInt64, UINT64, uint64_t); |
| PROTOBUF_DYN_EXTENSION_INFO_VARINT(SInt32, Int32, INT32, int32_t); |
| PROTOBUF_DYN_EXTENSION_INFO_VARINT(SInt64, Int64, INT64, int64_t); |
| PROTOBUF_DYN_EXTENSION_INFO_VARINT(Enum, Enum, ENUM, int); |
| |
| PROTOBUF_DYN_EXTENSION_INFO_FIXED(Fixed32, UInt32, UINT32, uint32_t); |
| PROTOBUF_DYN_EXTENSION_INFO_FIXED(Fixed64, UInt64, UINT64, uint64_t); |
| PROTOBUF_DYN_EXTENSION_INFO_FIXED(SFixed32, Int32, INT32, int32_t); |
| PROTOBUF_DYN_EXTENSION_INFO_FIXED(SFixed64, Int64, INT64, int64_t); |
| PROTOBUF_DYN_EXTENSION_INFO_FIXED(Double, Double, DOUBLE, double); |
| PROTOBUF_DYN_EXTENSION_INFO_FIXED(Float, Float, FLOAT, float); |
| PROTOBUF_DYN_EXTENSION_INFO_FIXED(Bool, Bool, BOOL, bool); |
| |
| #undef PROTOBUF_DYN_EXTENSION_INFO_VARINT |
| #undef PROTOBUF_DYN_EXTENSION_INFO_FIXED |
| |
| //////////////////////////////////////////////////////////////////////// |
| // Enum fields (to handle closed enums). |
| //////////////////////////////////////////////////////////////////////// |
| |
| template <typename MessageT, bool is_oneof_parameter> |
| struct EnumDynamicFieldInfo { |
| constexpr EnumDynamicFieldInfo(const Reflection* r, MessageT& m, |
| const FieldDescriptor* f) |
| : reflection(r), message(m), field(f) {} |
| |
| int number() const { return field->number(); } |
| FieldDescriptor::Type type() const { return field->type(); } |
| |
| int Get() const { |
| if constexpr (is_oneof) { |
| return reflection->GetEnumValue(message, field); |
| } else { |
| return DynamicFieldInfoHelper<false>::Get<int>(reflection, message, |
| field); |
| } |
| } |
| void Set(int value) { reflection->SetEnumValue(&message, field, value); } |
| void Clear() { |
| DynamicFieldInfoHelper<is_oneof>::ClearField(reflection, message, field); |
| } |
| size_t FieldByteSize() const { return WireFormatLite::EnumSize(Get()); } |
| |
| static constexpr FieldDescriptor::CppType cpp_type = // NOLINT |
| FieldDescriptor::CPPTYPE_ENUM; |
| static constexpr bool is_repeated = false; // NOLINT |
| static constexpr bool is_map = false; // NOLINT |
| static constexpr bool is_extension = false; // NOLINT |
| static constexpr bool is_oneof = is_oneof_parameter; // NOLINT |
| |
| const Reflection* reflection; |
| MessageT& message; |
| const FieldDescriptor* field; |
| }; |
| |
| //////////////////////////////////////////////////////////////////////// |
| // String fields |
| //////////////////////////////////////////////////////////////////////// |
| template <typename MessageT, bool is_oneof_parameter> |
| struct StringDynamicFieldInfo { |
| constexpr StringDynamicFieldInfo(const Reflection* r, MessageT& m, |
| const FieldDescriptor* f) |
| : reflection(r), message(m), field(f) {} |
| |
| int number() const { return field->number(); } |
| FieldDescriptor::Type type() const { return field->type(); } |
| |
| absl::string_view Get() const { |
| return DynamicFieldInfoHelper<is_oneof>::GetStringView(reflection, message, |
| field); |
| } |
| void Set(std::string value) { |
| reflection->SetString(&message, field, std::move(value)); |
| } |
| void Clear() { |
| DynamicFieldInfoHelper<is_oneof>::ClearField(reflection, message, field); |
| } |
| size_t FieldByteSize() const { return WireFormatLite::StringSize(Get()); } |
| |
| static constexpr FieldDescriptor::CppType cpp_type = // NOLINT |
| FieldDescriptor::CPPTYPE_STRING; |
| static constexpr bool is_repeated = false; // NOLINT |
| static constexpr bool is_map = false; // NOLINT |
| static constexpr bool is_extension = false; // NOLINT |
| static constexpr bool is_oneof = is_oneof_parameter; // NOLINT |
| static constexpr bool is_cord = false; // NOLINT |
| |
| const Reflection* reflection; |
| MessageT& message; |
| const FieldDescriptor* field; |
| }; |
| |
| //////////////////////////////////////////////////////////////////////// |
| // Extension string fields |
| //////////////////////////////////////////////////////////////////////// |
| template <typename ExtensionT> |
| struct StringDynamicExtensionInfo { |
| constexpr StringDynamicExtensionInfo(ExtensionT& e, int n) |
| : ext(e), ext_number(n) {} |
| |
| int number() const { return ext_number; } |
| FieldDescriptor::Type type() const { |
| return static_cast<FieldDescriptor::Type>(ext.type); |
| } |
| |
| absl::string_view Get() const { |
| return DynamicExtensionInfoHelper::GetStringView(ext); |
| } |
| void Set(absl::string_view value) { |
| DynamicExtensionInfoHelper::SetStringView(ext, value); |
| } |
| void Clear() { DynamicExtensionInfoHelper::ClearStringView(ext); } |
| size_t FieldByteSize() const { return WireFormatLite::StringSize(Get()); } |
| |
| static constexpr FieldDescriptor::CppType cpp_type = // NOLINT |
| FieldDescriptor::CPPTYPE_STRING; |
| static constexpr bool is_repeated = false; // NOLINT |
| static constexpr bool is_map = false; // NOLINT |
| static constexpr bool is_extension = true; // NOLINT |
| static constexpr bool is_oneof = false; // NOLINT |
| static constexpr bool is_cord = false; // NOLINT |
| |
| ExtensionT& ext; |
| int ext_number; |
| }; |
| |
| //////////////////////////////////////////////////////////////////////// |
| // Cord fields |
| //////////////////////////////////////////////////////////////////////// |
| template <typename MessageT, bool is_oneof_parameter> |
| struct CordDynamicFieldInfo { |
| constexpr CordDynamicFieldInfo(const Reflection* r, MessageT& m, |
| const FieldDescriptor* f) |
| : reflection(r), message(m), field(f) {} |
| |
| int number() const { return field->number(); } |
| FieldDescriptor::Type type() const { return field->type(); } |
| |
| ::absl::Cord Get() const { return reflection->GetCord(message, field); } |
| void Set(const ::absl::Cord& value) { |
| reflection->SetString(&message, field, value); |
| } |
| void Clear() { |
| DynamicFieldInfoHelper<is_oneof>::ClearField(reflection, message, field); |
| } |
| size_t FieldByteSize() const { return WireFormatLite::StringSize(Get()); } |
| |
| static constexpr FieldDescriptor::CppType cpp_type = // NOLINT |
| FieldDescriptor::CPPTYPE_STRING; |
| static constexpr bool is_repeated = false; // NOLINT |
| static constexpr bool is_map = false; // NOLINT |
| static constexpr bool is_extension = false; // NOLINT |
| static constexpr bool is_oneof = is_oneof_parameter; // NOLINT |
| static constexpr bool is_cord = true; // NOLINT |
| |
| const Reflection* reflection; |
| MessageT& message; |
| const FieldDescriptor* field; |
| }; |
| |
| //////////////////////////////////////////////////////////////////////// |
| // Message fields |
| //////////////////////////////////////////////////////////////////////// |
| template <typename MessageT, bool is_oneof_parameter> |
| struct MessageDynamicFieldInfo { |
| constexpr MessageDynamicFieldInfo(const Reflection* r, MessageT& m, |
| const FieldDescriptor* f) |
| : reflection(r), message(m), field(f) {} |
| |
| int number() const { return field->number(); } |
| FieldDescriptor::Type type() const { return field->type(); } |
| const Message& Get(MessageFactory* factory = nullptr) { |
| return reflection->GetMessage(message, field, factory); |
| } |
| Message& Mutable(MessageFactory* factory = nullptr) { |
| return *reflection->MutableMessage(&message, field, factory); |
| } |
| void Clear() { reflection->ClearField(&message, field); } |
| size_t FieldByteSize(MessageFactory* factory = nullptr) { |
| return Get(factory).ByteSizeLong(); |
| } |
| |
| static constexpr FieldDescriptor::CppType cpp_type = // NOLINT |
| FieldDescriptor::CPPTYPE_MESSAGE; |
| static constexpr bool is_repeated = false; // NOLINT |
| static constexpr bool is_map = false; // NOLINT |
| static constexpr bool is_extension = false; // NOLINT |
| static constexpr bool is_oneof = is_oneof_parameter; // NOLINT |
| static constexpr bool is_lazy = false; // NOLINT |
| |
| const Reflection* reflection; |
| MessageT& message; |
| const FieldDescriptor* field; |
| }; |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| // Extension message fields |
| //////////////////////////////////////////////////////////////////////// |
| struct SingularMessageDynamicExtensionInfo { |
| static constexpr FieldDescriptor::CppType cpp_type = // NOLINT |
| FieldDescriptor::CPPTYPE_MESSAGE; |
| static constexpr bool is_repeated = false; // NOLINT |
| static constexpr bool is_map = false; // NOLINT |
| static constexpr bool is_extension = true; // NOLINT |
| static constexpr bool is_oneof = false; // NOLINT |
| static constexpr bool is_lazy = false; // NOLINT |
| }; |
| |
| template <typename ExtensionT> |
| struct MessageDynamicExtensionInfo : SingularMessageDynamicExtensionInfo { |
| constexpr MessageDynamicExtensionInfo(ExtensionT& e, int n, bool mset) |
| : ext(e), ext_number(n), is_message_set(mset) {} |
| |
| int number() const { return ext_number; } |
| FieldDescriptor::Type type() const { |
| return static_cast<FieldDescriptor::Type>(ext.type); |
| } |
| const Message& Get() const { |
| return DynamicExtensionInfoHelper::GetMessage(ext); |
| } |
| Message& Mutable() { return DynamicExtensionInfoHelper::MutableMessage(ext); } |
| void Clear() { DynamicExtensionInfoHelper::ClearMessage(ext); } |
| size_t FieldByteSize() const { |
| return DynamicExtensionInfoHelper::GetMessage(ext).ByteSizeLong(); |
| } |
| |
| ExtensionT& ext; |
| int ext_number; |
| bool is_message_set; |
| }; |
| |
| template <typename ExtensionT> |
| struct GroupDynamicExtensionInfo : SingularMessageDynamicExtensionInfo { |
| constexpr GroupDynamicExtensionInfo(ExtensionT& e, int n) |
| : ext(e), ext_number(n), is_message_set(false) {} |
| |
| int number() const { return ext_number; } |
| FieldDescriptor::Type type() const { |
| return static_cast<FieldDescriptor::Type>(ext.type); |
| } |
| const Message& Get() const { |
| return DynamicExtensionInfoHelper::GetMessage(ext); |
| } |
| Message& Mutable() { return DynamicExtensionInfoHelper::MutableMessage(ext); } |
| void Clear() { DynamicExtensionInfoHelper::ClearMessage(ext); } |
| size_t FieldByteSize() const { |
| return DynamicExtensionInfoHelper::GetMessage(ext).ByteSizeLong(); |
| } |
| |
| ExtensionT& ext; |
| int ext_number; |
| bool is_message_set; |
| }; |
| |
| struct SingularLazyMessageDynamicExtensionInfo { |
| static constexpr FieldDescriptor::CppType cpp_type = // NOLINT |
| FieldDescriptor::CPPTYPE_MESSAGE; |
| static constexpr bool is_repeated = false; // NOLINT |
| static constexpr bool is_map = false; // NOLINT |
| static constexpr bool is_extension = true; // NOLINT |
| static constexpr bool is_oneof = false; // NOLINT |
| static constexpr bool is_lazy = true; // NOLINT |
| }; |
| |
| template <typename ExtensionT> |
| struct LazyMessageDynamicExtensionInfo |
| : SingularLazyMessageDynamicExtensionInfo { |
| LazyMessageDynamicExtensionInfo(ExtensionT& e, int n, bool mset, |
| const Message& p, Arena* a) |
| : ext(e), ext_number(n), is_message_set(mset), prototype(p), arena(a) {} |
| |
| int number() const { return ext_number; } |
| FieldDescriptor::Type type() const { |
| return static_cast<FieldDescriptor::Type>(ext.type); |
| } |
| const Message& Get() const { |
| return DynamicExtensionInfoHelper::GetLazyMessage(ext, prototype, arena); |
| } |
| const Message& GetIgnoreUnparsed() const { |
| return DynamicExtensionInfoHelper::GetLazyMessageIgnoreUnparsed( |
| ext, prototype, arena); |
| } |
| Message& Mutable() { |
| return DynamicExtensionInfoHelper::MutableLazyMessage(ext, prototype, |
| arena); |
| } |
| void Clear() { DynamicExtensionInfoHelper::ClearLazyMessage(ext); } |
| size_t FieldByteSize() const { |
| return DynamicExtensionInfoHelper::ByteSizeLongLazyMessage(ext); |
| } |
| |
| ExtensionT& ext; |
| int ext_number; |
| bool is_message_set; |
| const Message& prototype; |
| Arena* arena; |
| }; |
| |
| //////////////////////////////////////////////////////////////////////// |
| // Repeated fields |
| //////////////////////////////////////////////////////////////////////// |
| template <typename MessageT, typename FieldT> |
| struct RepeatedEntityDynamicFieldInfoBase { |
| constexpr RepeatedEntityDynamicFieldInfoBase(const Reflection* r, MessageT& m, |
| const FieldDescriptor* f, |
| const RepeatedField<FieldT>& rep) |
| : reflection(r), message(m), field(f), const_repeated(rep) {} |
| |
| int number() const { return field->number(); } |
| FieldDescriptor::Type type() const { return field->type(); } |
| bool is_packed() const { return field->is_packed(); } |
| |
| int size() const { return const_repeated.size(); } |
| iterator_range<typename RepeatedField<FieldT>::const_iterator> Get() const { |
| return {const_repeated.cbegin(), const_repeated.cend()}; |
| } |
| iterator_range<typename RepeatedField<FieldT>::iterator> Mutable() { |
| auto& rep = *reflection->MutableRepeatedField<FieldT>(&message, field); |
| return {rep.begin(), rep.end()}; |
| } |
| void Clear() { |
| reflection->MutableRepeatedField<FieldT>(&message, field)->Clear(); |
| } |
| |
| const Reflection* reflection; |
| MessageT& message; |
| const FieldDescriptor* field; |
| const RepeatedField<FieldT>& const_repeated; |
| }; |
| |
| #define PROTOBUF_DYN_FIELD_INFO_REPEATED_VARINT(NAME, CPPTYPE, FIELD_TYPE) \ |
| template <typename MessageT> \ |
| struct Repeated##NAME##DynamicFieldInfo \ |
| : RepeatedEntityDynamicFieldInfoBase<MessageT, FIELD_TYPE> { \ |
| using BaseT = RepeatedEntityDynamicFieldInfoBase<MessageT, FIELD_TYPE>; \ |
| \ |
| constexpr Repeated##NAME##DynamicFieldInfo( \ |
| const Reflection* r, MessageT& m, const FieldDescriptor* f, \ |
| const RepeatedField<FIELD_TYPE>& rep) \ |
| : BaseT(r, m, f, rep) {} \ |
| \ |
| size_t FieldByteSize() const { \ |
| size_t byte_size = 0; \ |
| for (auto it : BaseT::const_repeated) { \ |
| byte_size += WireFormatLite::NAME##Size(it); \ |
| } \ |
| return byte_size; \ |
| } \ |
| \ |
| static constexpr FieldDescriptor::CppType cpp_type = \ |
| FieldDescriptor::CPPTYPE_##CPPTYPE; \ |
| static constexpr bool is_repeated = true; \ |
| static constexpr bool is_map = false; \ |
| static constexpr bool is_extension = false; \ |
| static constexpr bool is_oneof = false; \ |
| }; |
| |
| #define PROTOBUF_DYN_FIELD_INFO_REPEATED_FIXED(NAME, CPPTYPE, FIELD_TYPE) \ |
| template <typename MessageT> \ |
| struct Repeated##NAME##DynamicFieldInfo \ |
| : RepeatedEntityDynamicFieldInfoBase<MessageT, FIELD_TYPE> { \ |
| using BaseT = RepeatedEntityDynamicFieldInfoBase<MessageT, FIELD_TYPE>; \ |
| \ |
| constexpr Repeated##NAME##DynamicFieldInfo( \ |
| const Reflection* r, MessageT& m, const FieldDescriptor* f, \ |
| const RepeatedField<FIELD_TYPE>& rep) \ |
| : BaseT(r, m, f, rep) {} \ |
| \ |
| size_t FieldByteSize() const { \ |
| return static_cast<size_t>(BaseT::size()) * \ |
| WireFormatLite::k##NAME##Size; \ |
| } \ |
| \ |
| static constexpr FieldDescriptor::CppType cpp_type = \ |
| FieldDescriptor::CPPTYPE_##CPPTYPE; \ |
| static constexpr bool is_repeated = true; \ |
| static constexpr bool is_map = false; \ |
| static constexpr bool is_extension = false; \ |
| static constexpr bool is_oneof = false; \ |
| }; |
| |
| PROTOBUF_DYN_FIELD_INFO_REPEATED_VARINT(Int32, INT32, int32_t); |
| PROTOBUF_DYN_FIELD_INFO_REPEATED_VARINT(Int64, INT64, int64_t); |
| PROTOBUF_DYN_FIELD_INFO_REPEATED_VARINT(UInt32, UINT32, uint32_t); |
| PROTOBUF_DYN_FIELD_INFO_REPEATED_VARINT(UInt64, UINT64, uint64_t); |
| PROTOBUF_DYN_FIELD_INFO_REPEATED_VARINT(SInt32, INT32, int32_t); |
| PROTOBUF_DYN_FIELD_INFO_REPEATED_VARINT(SInt64, INT64, int64_t); |
| PROTOBUF_DYN_FIELD_INFO_REPEATED_VARINT(Enum, ENUM, int); |
| |
| PROTOBUF_DYN_FIELD_INFO_REPEATED_FIXED(Fixed32, UINT32, uint32_t); |
| PROTOBUF_DYN_FIELD_INFO_REPEATED_FIXED(Fixed64, UINT64, uint64_t); |
| PROTOBUF_DYN_FIELD_INFO_REPEATED_FIXED(SFixed32, INT32, int32_t); |
| PROTOBUF_DYN_FIELD_INFO_REPEATED_FIXED(SFixed64, INT64, int64_t); |
| PROTOBUF_DYN_FIELD_INFO_REPEATED_FIXED(Double, DOUBLE, double); |
| PROTOBUF_DYN_FIELD_INFO_REPEATED_FIXED(Float, FLOAT, float); |
| PROTOBUF_DYN_FIELD_INFO_REPEATED_FIXED(Bool, BOOL, bool); |
| |
| #undef PROTOBUF_DYN_FIELD_INFO_REPEATED_VARINT |
| #undef PROTOBUF_DYN_FIELD_INFO_REPEATED_FIXED |
| |
| template <typename MessageT, typename FieldT> |
| struct RepeatedPtrEntityDynamicFieldInfoBase { |
| constexpr RepeatedPtrEntityDynamicFieldInfoBase( |
| const Reflection* r, MessageT& m, const FieldDescriptor* f, |
| const RepeatedPtrField<FieldT>& rep) |
| : reflection(r), message(m), field(f), const_repeated(rep) {} |
| |
| int number() const { return field->number(); } |
| FieldDescriptor::Type type() const { return field->type(); } |
| bool is_packed() const { return field->is_packed(); } |
| |
| int size() const { return const_repeated.size(); } |
| iterator_range<typename RepeatedPtrField<FieldT>::const_iterator> Get() |
| const { |
| return {const_repeated.cbegin(), const_repeated.cend()}; |
| } |
| iterator_range<typename RepeatedPtrField<FieldT>::iterator> Mutable() { |
| auto& rep = *reflection->MutableRepeatedPtrField<FieldT>(&message, field); |
| return {rep.begin(), rep.end()}; |
| } |
| void Clear() { |
| reflection->MutableRepeatedPtrField<FieldT>(&message, field)->Clear(); |
| } |
| |
| const Reflection* reflection; |
| MessageT& message; |
| const FieldDescriptor* field; |
| const RepeatedPtrField<FieldT>& const_repeated; |
| }; |
| |
| template <typename MessageT, typename FieldT> |
| struct RepeatedStringDynamicFieldInfoBase |
| : RepeatedPtrEntityDynamicFieldInfoBase<MessageT, FieldT> { |
| using BaseT = RepeatedPtrEntityDynamicFieldInfoBase<MessageT, FieldT>; |
| |
| constexpr RepeatedStringDynamicFieldInfoBase( |
| const Reflection* r, MessageT& m, const FieldDescriptor* f, |
| const RepeatedPtrField<FieldT>& rep) |
| : BaseT(r, m, f, rep) {} |
| size_t FieldByteSize() const { |
| size_t byte_size = 0; |
| for (auto& it : BaseT::const_repeated) { |
| byte_size += WireFormatLite::LengthDelimitedSize(it.size()); |
| } |
| return byte_size; |
| } |
| }; |
| |
| template <typename MessageT> |
| struct RepeatedStringDynamicFieldInfo |
| : RepeatedStringDynamicFieldInfoBase<MessageT, std::string> { |
| constexpr RepeatedStringDynamicFieldInfo( |
| const Reflection* r, MessageT& m, const FieldDescriptor* f, |
| const RepeatedPtrField<std::string>& rep) |
| : RepeatedStringDynamicFieldInfoBase<MessageT, std::string>(r, m, f, |
| rep) {} |
| |
| static constexpr FieldDescriptor::CppType cpp_type = // NOLINT |
| FieldDescriptor::CPPTYPE_STRING; |
| static constexpr bool is_repeated = true; // NOLINT |
| static constexpr bool is_map = false; // NOLINT |
| static constexpr bool is_extension = false; // NOLINT |
| static constexpr bool is_oneof = false; // NOLINT |
| static constexpr bool is_cord = false; // NOLINT |
| static constexpr bool is_string_piece = false; // NOLINT |
| }; |
| |
| |
| struct RepeatedMessageDynamicFieldInfoMeta { |
| static constexpr FieldDescriptor::CppType cpp_type = // NOLINT |
| FieldDescriptor::CPPTYPE_MESSAGE; |
| static constexpr bool is_repeated = true; // NOLINT |
| static constexpr bool is_map = false; // NOLINT |
| static constexpr bool is_extension = false; // NOLINT |
| static constexpr bool is_oneof = false; // NOLINT |
| }; |
| |
| template <typename MessageT> |
| struct RepeatedMessageDynamicFieldInfo |
| : RepeatedPtrEntityDynamicFieldInfoBase<MessageT, Message>, |
| RepeatedMessageDynamicFieldInfoMeta { |
| using BaseT = RepeatedPtrEntityDynamicFieldInfoBase<MessageT, Message>; |
| |
| constexpr RepeatedMessageDynamicFieldInfo( |
| const Reflection* r, MessageT& m, const FieldDescriptor* f, |
| const RepeatedPtrField<Message>& rep) |
| : BaseT(r, m, f, rep) {} |
| |
| size_t FieldByteSize() const { |
| size_t byte_size = 0; |
| for (auto& it : BaseT::const_repeated) { |
| byte_size += WireFormatLite::LengthDelimitedSize(it.ByteSizeLong()); |
| } |
| return byte_size; |
| } |
| }; |
| |
| template <typename MessageT> |
| struct RepeatedGroupDynamicFieldInfo |
| : RepeatedPtrEntityDynamicFieldInfoBase<MessageT, Message>, |
| RepeatedMessageDynamicFieldInfoMeta { |
| using BaseT = RepeatedPtrEntityDynamicFieldInfoBase<MessageT, Message>; |
| |
| constexpr RepeatedGroupDynamicFieldInfo(const Reflection* r, MessageT& m, |
| const FieldDescriptor* f, |
| const RepeatedPtrField<Message>& rep) |
| : BaseT(r, m, f, rep) {} |
| |
| size_t FieldByteSize() const { |
| size_t byte_size = 0; |
| for (auto& it : BaseT::const_repeated) { |
| byte_size += it.ByteSizeLong(); |
| } |
| return byte_size; |
| } |
| }; |
| |
| //////////////////////////////////////////////////////////////////////// |
| // Extension repeated fields |
| //////////////////////////////////////////////////////////////////////// |
| #define PROTOBUF_DYN_EXTENSION_INFO_REPEATED_VARINT(NAME, CPPNAME, CPPTYPE, \ |
| FIELD_TYPE) \ |
| template <typename ExtensionT> \ |
| struct Repeated##NAME##DynamicExtensionInfo { \ |
| constexpr Repeated##NAME##DynamicExtensionInfo(ExtensionT& e, int n) \ |
| : ext(e), ext_number(n) {} \ |
| \ |
| int number() const { return ext_number; } \ |
| FieldDescriptor::Type type() const { \ |
| return static_cast<FieldDescriptor::Type>(ext.type); \ |
| } \ |
| bool is_packed() const { return ext.is_packed; } \ |
| \ |
| int size() const { \ |
| return DynamicExtensionInfoHelper::GetRepeated##CPPNAME(ext)->size(); \ |
| } \ |
| const RepeatedField<FIELD_TYPE>& Get() const { \ |
| return *DynamicExtensionInfoHelper::GetRepeated##CPPNAME(ext); \ |
| } \ |
| RepeatedField<FIELD_TYPE>& Mutable() { \ |
| return *DynamicExtensionInfoHelper::MutableRepeated##CPPNAME(ext); \ |
| } \ |
| void Clear() { \ |
| DynamicExtensionInfoHelper::MutableRepeated##CPPNAME(ext)->Clear(); \ |
| } \ |
| size_t FieldByteSize() const { \ |
| size_t byte_size = 0; \ |
| for (auto it : Get()) { \ |
| byte_size += WireFormatLite::NAME##Size(it); \ |
| } \ |
| return byte_size; \ |
| } \ |
| \ |
| static constexpr FieldDescriptor::CppType cpp_type = \ |
| FieldDescriptor::CPPTYPE_##CPPTYPE; \ |
| static constexpr bool is_repeated = true; \ |
| static constexpr bool is_map = false; \ |
| static constexpr bool is_extension = true; \ |
| static constexpr bool is_oneof = false; \ |
| \ |
| ExtensionT& ext; \ |
| int ext_number; \ |
| }; |
| |
| #define PROTOBUF_DYN_EXTENSION_INFO_REPEATED_FIXED(NAME, CPPNAME, CPPTYPE, \ |
| FIELD_TYPE) \ |
| template <typename ExtensionT> \ |
| struct Repeated##NAME##DynamicExtensionInfo { \ |
| constexpr Repeated##NAME##DynamicExtensionInfo(ExtensionT& e, int n) \ |
| : ext(e), ext_number(n) {} \ |
| \ |
| int number() const { return ext_number; } \ |
| FieldDescriptor::Type type() const { \ |
| return static_cast<FieldDescriptor::Type>(ext.type); \ |
| } \ |
| bool is_packed() const { return ext.is_packed; } \ |
| \ |
| int size() const { \ |
| return DynamicExtensionInfoHelper::GetRepeated##CPPNAME(ext)->size(); \ |
| } \ |
| const RepeatedField<FIELD_TYPE>& Get() const { \ |
| return *DynamicExtensionInfoHelper::GetRepeated##CPPNAME(ext); \ |
| } \ |
| RepeatedField<FIELD_TYPE>& Mutable() { \ |
| return *DynamicExtensionInfoHelper::MutableRepeated##CPPNAME(ext); \ |
| } \ |
| void Clear() { \ |
| DynamicExtensionInfoHelper::MutableRepeated##CPPNAME(ext)->Clear(); \ |
| } \ |
| size_t FieldByteSize() const { \ |
| return static_cast<size_t>(size()) * WireFormatLite::k##NAME##Size; \ |
| } \ |
| \ |
| static constexpr FieldDescriptor::CppType cpp_type = \ |
| FieldDescriptor::CPPTYPE_##CPPTYPE; \ |
| static constexpr bool is_repeated = true; \ |
| static constexpr bool is_map = false; \ |
| static constexpr bool is_extension = true; \ |
| static constexpr bool is_oneof = false; \ |
| \ |
| ExtensionT& ext; \ |
| int ext_number; \ |
| }; |
| |
| PROTOBUF_DYN_EXTENSION_INFO_REPEATED_VARINT(Int32, Int32, INT32, int32_t); |
| PROTOBUF_DYN_EXTENSION_INFO_REPEATED_VARINT(Int64, Int64, INT64, int64_t); |
| PROTOBUF_DYN_EXTENSION_INFO_REPEATED_VARINT(UInt32, UInt32, UINT32, uint32_t); |
| PROTOBUF_DYN_EXTENSION_INFO_REPEATED_VARINT(UInt64, UInt64, UINT64, uint64_t); |
| PROTOBUF_DYN_EXTENSION_INFO_REPEATED_VARINT(SInt32, Int32, INT32, int32_t); |
| PROTOBUF_DYN_EXTENSION_INFO_REPEATED_VARINT(SInt64, Int64, INT64, int64_t); |
| PROTOBUF_DYN_EXTENSION_INFO_REPEATED_VARINT(Enum, Enum, ENUM, int); |
| |
| PROTOBUF_DYN_EXTENSION_INFO_REPEATED_FIXED(Fixed32, UInt32, UINT32, uint32_t); |
| PROTOBUF_DYN_EXTENSION_INFO_REPEATED_FIXED(Fixed64, UInt64, UINT64, uint64_t); |
| PROTOBUF_DYN_EXTENSION_INFO_REPEATED_FIXED(SFixed32, Int32, INT32, int32_t); |
| PROTOBUF_DYN_EXTENSION_INFO_REPEATED_FIXED(SFixed64, Int64, INT64, int64_t); |
| PROTOBUF_DYN_EXTENSION_INFO_REPEATED_FIXED(Double, Double, DOUBLE, double); |
| PROTOBUF_DYN_EXTENSION_INFO_REPEATED_FIXED(Float, Float, FLOAT, float); |
| PROTOBUF_DYN_EXTENSION_INFO_REPEATED_FIXED(Bool, Bool, BOOL, bool); |
| |
| #undef PROTOBUF_DYN_EXTENSION_INFO_REPEATED_VARINT |
| #undef PROTOBUF_DYN_EXTENSION_INFO_REPEATED_FIXED |
| |
| template <typename ExtensionT> |
| struct RepeatedStringDynamicExtensionInfo { |
| constexpr RepeatedStringDynamicExtensionInfo(ExtensionT& ext, int n) |
| : ext(ext), ext_number(n) {} |
| |
| int number() const { return ext_number; } |
| FieldDescriptor::Type type() const { |
| return static_cast<FieldDescriptor::Type>(ext.type); |
| } |
| constexpr bool is_packed() const { return false; } |
| |
| int size() const { |
| return DynamicExtensionInfoHelper::GetRepeatedString(ext)->size(); |
| } |
| const RepeatedPtrField<std::string>& Get() const { |
| return *DynamicExtensionInfoHelper::GetRepeatedString(ext); |
| } |
| RepeatedPtrField<std::string>& Mutable() { |
| return *DynamicExtensionInfoHelper::MutableRepeatedString(ext); |
| } |
| void Clear() { |
| DynamicExtensionInfoHelper::MutableRepeatedString(ext)->Clear(); |
| } |
| size_t FieldByteSize() const { |
| size_t byte_size = 0; |
| for (auto& it : Get()) { |
| byte_size += WireFormatLite::LengthDelimitedSize(it.size()); |
| } |
| return byte_size; |
| } |
| |
| static constexpr FieldDescriptor::CppType cpp_type = // NOLINT |
| FieldDescriptor::CPPTYPE_STRING; |
| static constexpr bool is_repeated = true; // NOLINT |
| static constexpr bool is_map = false; // NOLINT |
| static constexpr bool is_extension = true; // NOLINT |
| static constexpr bool is_oneof = false; // NOLINT |
| static constexpr bool is_cord = false; // NOLINT |
| static constexpr bool is_string_piece = false; // NOLINT |
| |
| ExtensionT& ext; |
| int ext_number; |
| }; |
| |
| template <typename ExtensionT> |
| struct RepeatedMessageDynamicExtensionInfoBase { |
| constexpr RepeatedMessageDynamicExtensionInfoBase(ExtensionT& e, int n) |
| : ext(e), ext_number(n) {} |
| |
| int number() const { return ext_number; } |
| FieldDescriptor::Type type() const { |
| return static_cast<FieldDescriptor::Type>(ext.type); |
| } |
| constexpr bool is_packed() const { return false; } |
| |
| int size() const { |
| return DynamicExtensionInfoHelper::GetRepeatedMessage(ext)->size(); |
| } |
| const RepeatedPtrField<MessageLite>& Get() const { |
| return *DynamicExtensionInfoHelper::GetRepeatedMessage(ext); |
| } |
| RepeatedPtrField<MessageLite>& Mutable() { |
| return *DynamicExtensionInfoHelper::MutableRepeatedMessage(ext); |
| } |
| void Clear() { |
| DynamicExtensionInfoHelper::MutableRepeatedMessage(ext)->Clear(); |
| } |
| |
| static constexpr FieldDescriptor::CppType cpp_type = // NOLINT |
| FieldDescriptor::CPPTYPE_MESSAGE; |
| static constexpr bool is_repeated = true; // NOLINT |
| static constexpr bool is_map = false; // NOLINT |
| static constexpr bool is_extension = true; // NOLINT |
| static constexpr bool is_oneof = false; // NOLINT |
| |
| ExtensionT& ext; |
| int ext_number; |
| }; |
| |
| template <typename ExtensionT> |
| struct RepeatedMessageDynamicExtensionInfo |
| : RepeatedMessageDynamicExtensionInfoBase<ExtensionT> { |
| using BaseT = RepeatedMessageDynamicExtensionInfoBase<ExtensionT>; |
| |
| constexpr RepeatedMessageDynamicExtensionInfo(ExtensionT& e, int n) |
| : BaseT(e, n) {} |
| |
| size_t FieldByteSize() const { |
| size_t byte_size = 0; |
| for (auto& it : BaseT::Get()) { |
| byte_size += WireFormatLite::LengthDelimitedSize(it.ByteSizeLong()); |
| } |
| return byte_size; |
| } |
| }; |
| |
| template <typename ExtensionT> |
| struct RepeatedGroupDynamicExtensionInfo |
| : RepeatedMessageDynamicExtensionInfoBase<ExtensionT> { |
| using BaseT = RepeatedMessageDynamicExtensionInfoBase<ExtensionT>; |
| |
| constexpr RepeatedGroupDynamicExtensionInfo(ExtensionT& e, int n) |
| : BaseT(e, n) {} |
| |
| size_t FieldByteSize() const { |
| size_t byte_size = 0; |
| for (auto& it : BaseT::Get()) { |
| byte_size += it.ByteSizeLong(); |
| } |
| return byte_size; |
| } |
| }; |
| |
| //////////////////////////////////////////////////////////////////////// |
| // Map fields |
| //////////////////////////////////////////////////////////////////////// |
| |
| // Returns the encoded size for (cpp_type, type, value). Some types are fixed |
| // sized; while others are variable. Dispatch done here at compile time frees |
| // users from a similar dispatch without creating KeyInfo or ValueInfo per type. |
| template <FieldDescriptor::CppType cpp_type, typename T> |
| inline size_t MapPrimitiveFieldByteSize(FieldDescriptor::Type type, T value) { |
| if constexpr (cpp_type == FieldDescriptor::CPPTYPE_INT32) { |
| static_assert(std::is_same_v<T, int32_t>, "type mismatch"); |
| switch (type) { |
| case FieldDescriptor::TYPE_INT32: |
| return WireFormatLite::Int32Size(value); |
| case FieldDescriptor::TYPE_SINT32: |
| return WireFormatLite::SInt32Size(value); |
| case FieldDescriptor::TYPE_SFIXED32: |
| return WireFormatLite::kSFixed32Size; |
| default: |
| Unreachable(); |
| } |
| } else if constexpr (cpp_type == FieldDescriptor::CPPTYPE_INT64) { |
| static_assert(std::is_same_v<T, int64_t>, "type mismatch"); |
| switch (type) { |
| case FieldDescriptor::TYPE_INT64: |
| return WireFormatLite::Int64Size(value); |
| case FieldDescriptor::TYPE_SINT64: |
| return WireFormatLite::SInt64Size(value); |
| case FieldDescriptor::TYPE_SFIXED64: |
| return WireFormatLite::kSFixed64Size; |
| default: |
| Unreachable(); |
| } |
| } else if constexpr (cpp_type == FieldDescriptor::CPPTYPE_UINT32) { |
| static_assert(std::is_same_v<T, uint32_t>, "type mismatch"); |
| switch (type) { |
| case FieldDescriptor::TYPE_UINT32: |
| return WireFormatLite::UInt32Size(value); |
| case FieldDescriptor::TYPE_FIXED32: |
| return WireFormatLite::kSFixed32Size; |
| default: |
| Unreachable(); |
| } |
| } else if constexpr (cpp_type == FieldDescriptor::CPPTYPE_UINT64) { |
| static_assert(std::is_same_v<T, uint64_t>, "type mismatch"); |
| switch (type) { |
| case FieldDescriptor::TYPE_UINT64: |
| return WireFormatLite::UInt64Size(value); |
| case FieldDescriptor::TYPE_FIXED64: |
| return WireFormatLite::kSFixed64Size; |
| default: |
| Unreachable(); |
| } |
| } else if constexpr (cpp_type == FieldDescriptor::CPPTYPE_ENUM) { |
| static_assert(std::is_same_v<T, int>, "type mismatch"); |
| return WireFormatLite::EnumSize(value); |
| } else if constexpr (cpp_type == FieldDescriptor::CPPTYPE_BOOL) { |
| static_assert(std::is_same_v<T, bool>, "type mismatch"); |
| return WireFormatLite::kBoolSize; |
| } else if constexpr (cpp_type == FieldDescriptor::CPPTYPE_FLOAT) { |
| static_assert(std::is_same_v<T, float>, "type mismatch"); |
| return WireFormatLite::kFloatSize; |
| } else if constexpr (cpp_type == FieldDescriptor::CPPTYPE_DOUBLE) { |
| static_assert(std::is_same_v<T, double>, "type mismatch"); |
| return WireFormatLite::kDoubleSize; |
| } |
| } |
| |
| #define PROTOBUF_MAP_KEY_INFO(NAME, KEY_TYPE, CPPTYPE) \ |
| struct MapDynamicField##NAME##KeyInfo { \ |
| explicit MapDynamicField##NAME##KeyInfo(const MapKey& k) : key(k) { \ |
| ABSL_DCHECK_EQ(cpp_type, key.type()); \ |
| } \ |
| \ |
| KEY_TYPE Get() const { return key.Get##NAME##Value(); } \ |
| /* Set() API doesn't make sense because MapIter always returns const \ |
| * MapKey&. */ \ |
| \ |
| static constexpr FieldDescriptor::CppType cpp_type = \ |
| FieldDescriptor::CPPTYPE_##CPPTYPE; \ |
| \ |
| const MapKey& key; \ |
| }; |
| |
| PROTOBUF_MAP_KEY_INFO(Int32, int32_t, INT32); |
| PROTOBUF_MAP_KEY_INFO(Int64, int64_t, INT64); |
| PROTOBUF_MAP_KEY_INFO(UInt32, uint32_t, UINT32); |
| PROTOBUF_MAP_KEY_INFO(UInt64, uint64_t, UINT64); |
| PROTOBUF_MAP_KEY_INFO(Bool, bool, BOOL); |
| PROTOBUF_MAP_KEY_INFO(String, const std::string&, STRING); |
| |
| #undef PROTOBUF_MAP_KEY_INFO |
| |
| #define PROTOBUF_MAP_VALUE_INFO(NAME, VALUE_TYPE, CPPTYPE) \ |
| template <typename MapValueRefT> \ |
| struct MapDynamicField##NAME##ValueInfo { \ |
| explicit MapDynamicField##NAME##ValueInfo(MapValueRefT& v) : value(v) { \ |
| ABSL_DCHECK_EQ(cpp_type, value.type()); \ |
| } \ |
| \ |
| VALUE_TYPE Get() const { return value.Get##NAME##Value(); } \ |
| void Set(VALUE_TYPE val) { value.Set##NAME##Value(val); } \ |
| \ |
| static constexpr FieldDescriptor::CppType cpp_type = \ |
| FieldDescriptor::CPPTYPE_##CPPTYPE; \ |
| \ |
| MapValueRefT& value; \ |
| }; |
| |
| PROTOBUF_MAP_VALUE_INFO(Int32, int32_t, INT32); |
| PROTOBUF_MAP_VALUE_INFO(Int64, int64_t, INT64); |
| PROTOBUF_MAP_VALUE_INFO(UInt32, uint32_t, UINT32); |
| PROTOBUF_MAP_VALUE_INFO(UInt64, uint64_t, UINT64); |
| PROTOBUF_MAP_VALUE_INFO(Bool, bool, BOOL); |
| PROTOBUF_MAP_VALUE_INFO(Enum, int, ENUM); |
| PROTOBUF_MAP_VALUE_INFO(Float, float, FLOAT); |
| PROTOBUF_MAP_VALUE_INFO(Double, double, DOUBLE); |
| PROTOBUF_MAP_VALUE_INFO(String, const std::string&, STRING); |
| |
| #undef PROTOBUF_MAP_VALUE_INFO |
| |
| template <typename MapValueRefT> |
| struct MapDynamicFieldMessageValueInfo { |
| explicit constexpr MapDynamicFieldMessageValueInfo(MapValueRefT& v) |
| : value(v) {} |
| |
| const Message& Get() const { return value.GetMessageValue(); } |
| Message* Mutable() { return value.MutableMessageValue(); } |
| |
| static constexpr FieldDescriptor::CppType cpp_type = // NOLINT |
| FieldDescriptor::CPPTYPE_MESSAGE; |
| |
| MapValueRefT& value; |
| }; |
| |
| // Calls "cb" with the corresponding ValueInfo. Typically called from |
| // MapDynamicFieldVisitKey. |
| template <typename MapValueRefT, typename MapValueCallback> |
| void MapDynamicFieldVisitValue(MapValueRefT& value, MapValueCallback&& cb) { |
| switch (value.type()) { |
| #define PROTOBUF_HANDLE_MAP_VALUE_CASE(NAME, VALUE_TYPE, CPPTYPE) \ |
| case FieldDescriptor::CPPTYPE_##CPPTYPE: \ |
| cb(MapDynamicField##NAME##ValueInfo<MapValueRefT>{value}); \ |
| break; |
| |
| PROTOBUF_HANDLE_MAP_VALUE_CASE(Int32, int32_t, INT32); |
| PROTOBUF_HANDLE_MAP_VALUE_CASE(Int64, int64_t, INT64); |
| PROTOBUF_HANDLE_MAP_VALUE_CASE(UInt32, uint32_t, UINT32); |
| PROTOBUF_HANDLE_MAP_VALUE_CASE(UInt64, uint64_t, UINT64); |
| PROTOBUF_HANDLE_MAP_VALUE_CASE(Bool, bool, BOOL); |
| PROTOBUF_HANDLE_MAP_VALUE_CASE(Enum, int, ENUM); |
| PROTOBUF_HANDLE_MAP_VALUE_CASE(Float, float, FLOAT); |
| PROTOBUF_HANDLE_MAP_VALUE_CASE(Double, double, DOUBLE); |
| PROTOBUF_HANDLE_MAP_VALUE_CASE(String, std::string, STRING); |
| PROTOBUF_HANDLE_MAP_VALUE_CASE(Message, Message, MESSAGE); |
| |
| default: |
| internal::Unreachable(); |
| |
| #undef PROTOBUF_HANDLE_MAP_VALUE_CASE |
| } |
| } |
| |
| // Dispatches based on key type to instantiate a right KeyInfo, then calls |
| // MapDynamicFieldVisitValue to dispatch on the value type. |
| template <typename MapValueRefT, typename MapFieldCallback> |
| void MapDynamicFieldVisitKey(const MapKey& key, MapValueRefT& value, |
| const MapFieldCallback& user_cb) { |
| switch (key.type()) { |
| #define PROTOBUF_HANDLE_MAP_KEY_CASE(NAME, CPPTYPE) \ |
| case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ |
| auto key_info = MapDynamicField##NAME##KeyInfo{key}; \ |
| MapDynamicFieldVisitValue(value, [key_info, &user_cb](auto&& value_info) { \ |
| user_cb(key_info, value_info); \ |
| }); \ |
| break; \ |
| } |
| |
| PROTOBUF_HANDLE_MAP_KEY_CASE(Int32, INT32); |
| PROTOBUF_HANDLE_MAP_KEY_CASE(Int64, INT64); |
| PROTOBUF_HANDLE_MAP_KEY_CASE(UInt32, UINT32); |
| PROTOBUF_HANDLE_MAP_KEY_CASE(UInt64, UINT64); |
| PROTOBUF_HANDLE_MAP_KEY_CASE(Bool, BOOL); |
| PROTOBUF_HANDLE_MAP_KEY_CASE(String, STRING); |
| |
| #undef PROTOBUF_HANDLE_MAP_KEY_CASE |
| |
| default: |
| internal::Unreachable(); |
| break; |
| } |
| } |
| |
| template <typename MessageT> |
| struct MapDynamicFieldInfo { |
| constexpr MapDynamicFieldInfo(const Reflection* r, MessageT& m, |
| const FieldDescriptor* f, |
| const FieldDescriptor* key_f, |
| const FieldDescriptor* val_f, |
| const MapFieldBase& map_field) |
| : reflection(r), |
| message(m), |
| field(f), |
| key(key_f), |
| value(val_f), |
| const_map_field(map_field) { |
| ABSL_DCHECK(f->is_map()); |
| ABSL_DCHECK_NE(key_f, nullptr); |
| ABSL_DCHECK_NE(val_f, nullptr); |
| } |
| |
| int number() const { return field->number(); } |
| FieldDescriptor::Type key_type() const { return key->type(); } |
| FieldDescriptor::Type value_type() const { return value->type(); } |
| int size() const { return const_map_field.size(); } |
| |
| // go/ranked-overloads for the rationale. |
| struct Rank0 {}; |
| struct Rank1 : Rank0 {}; |
| |
| // Preferred version when "msg" is non-const. |
| template <typename T, typename Callback, |
| typename = std::enable_if_t<!std::is_const_v<T>>> |
| static void VisitElementsImpl(T& msg, const Reflection* reflection, |
| const FieldDescriptor* field, |
| const MapFieldBase&, Callback&& cb, Rank1) { |
| auto& map_field = |
| DynamicFieldInfoHelper<false>::template Mutable<MapFieldBase>( |
| reflection, msg, field); |
| const Descriptor* descriptor = field->message_type(); |
| MapIterator begin(&map_field, descriptor), end(&map_field, descriptor); |
| map_field.MapBegin(&begin); |
| map_field.MapEnd(&end); |
| |
| for (auto it = begin; it != end; ++it) { |
| MapDynamicFieldVisitKey(it.GetKey(), *it.MutableValueRef(), cb); |
| } |
| } |
| |
| // Fallback version otherwise. |
| template <typename T, typename Callback> |
| static void VisitElementsImpl(T& msg, const Reflection*, |
| const FieldDescriptor* field, |
| const MapFieldBase& const_map_field, |
| Callback&& cb, Rank0) { |
| // Unfortunately, we have to const_cast here because MapIterator only takes |
| // a mutable MapFieldBase pointer. This is still safe because value iterator |
| // is not mutable. |
| MapFieldBase* map_field = const_cast<MapFieldBase*>(&const_map_field); |
| const Descriptor* descriptor = field->message_type(); |
| MapIterator begin(map_field, descriptor), end(map_field, descriptor); |
| const_map_field.MapBegin(&begin); |
| const_map_field.MapEnd(&end); |
| |
| for (auto it = begin; it != end; ++it) { |
| MapDynamicFieldVisitKey(it.GetKey(), it.GetValueRef(), cb); |
| } |
| } |
| |
| template <typename MapFieldCallback> |
| void VisitElements(MapFieldCallback&& cb) const { |
| VisitElementsImpl(message, reflection, field, const_map_field, |
| static_cast<MapFieldCallback&&>(cb), Rank1{}); |
| } |
| |
| void Clear() { |
| auto& map_field = |
| DynamicFieldInfoHelper<false>::template Mutable<MapFieldBase>( |
| reflection, message, field); |
| |
| map_field.Clear(); |
| } |
| |
| static constexpr bool is_repeated = true; // NOLINT |
| static constexpr bool is_packed = false; // NOLINT |
| static constexpr bool is_map = true; // NOLINT |
| static constexpr bool is_extension = false; // NOLINT |
| static constexpr bool is_oneof = false; // NOLINT |
| |
| const Reflection* reflection; |
| MessageT& message; |
| const FieldDescriptor* field; |
| const FieldDescriptor* key; |
| const FieldDescriptor* value; |
| const MapFieldBase& const_map_field; |
| }; |
| |
| #endif // __cpp_if_constexpr |
| |
| } // namespace internal |
| } // namespace protobuf |
| } // namespace google |
| |
| #include "google/protobuf/port_undef.inc" |
| |
| #endif // GOOGLE_PROTOBUF_REFLECTION_VISIT_FIELD_INFO_H__ |