File indexing completed on 2025-01-31 10:12:25
0001 #ifndef GOOGLE_PROTOBUF_REFLECTION_VISIT_FIELDS_H__
0002 #define GOOGLE_PROTOBUF_REFLECTION_VISIT_FIELDS_H__
0003
0004 #include <cstdint>
0005 #include <string>
0006 #include <utility>
0007
0008 #include "absl/base/attributes.h"
0009 #include "absl/log/absl_check.h"
0010 #include "absl/strings/cord.h"
0011 #include "google/protobuf/descriptor.h"
0012 #include "google/protobuf/descriptor.pb.h"
0013 #include "google/protobuf/descriptor_lite.h"
0014 #include "google/protobuf/extension_set.h"
0015 #include "google/protobuf/generated_message_reflection.h"
0016 #include "google/protobuf/message.h"
0017 #include "google/protobuf/port.h"
0018 #include "google/protobuf/reflection.h"
0019 #include "google/protobuf/reflection_visit_field_info.h"
0020 #include "google/protobuf/repeated_field.h"
0021 #include "google/protobuf/repeated_ptr_field.h"
0022
0023
0024
0025 #include "google/protobuf/port_def.inc" // NOLINT
0026
0027 namespace google {
0028 namespace protobuf {
0029 namespace internal {
0030
0031 enum class FieldMask : uint32_t {
0032 kInt32 = 1 << FieldDescriptor::CPPTYPE_INT32,
0033 kInt64 = 1 << FieldDescriptor::CPPTYPE_INT64,
0034 kUInt32 = 1 << FieldDescriptor::CPPTYPE_UINT32,
0035 kUInt64 = 1 << FieldDescriptor::CPPTYPE_UINT64,
0036 kDouble = 1 << FieldDescriptor::CPPTYPE_DOUBLE,
0037 kFloat = 1 << FieldDescriptor::CPPTYPE_FLOAT,
0038 kBool = 1 << FieldDescriptor::CPPTYPE_BOOL,
0039 kEnum = 1 << FieldDescriptor::CPPTYPE_ENUM,
0040 kString = 1 << FieldDescriptor::CPPTYPE_STRING,
0041 kMessage = 1 << FieldDescriptor::CPPTYPE_MESSAGE,
0042 kPrimitive =
0043 kInt32 | kInt64 | kUInt32 | kUInt64 | kDouble | kFloat | kBool | kEnum,
0044 kAll = 0xFFFFFFFFu,
0045 };
0046
0047 inline FieldMask operator|(FieldMask lhs, FieldMask rhs) {
0048 return static_cast<FieldMask>(static_cast<uint32_t>(lhs) |
0049 static_cast<uint32_t>(rhs));
0050 }
0051
0052 #ifdef __cpp_if_constexpr
0053
0054 template <typename MessageT, typename CallbackFn>
0055 void VisitFields(MessageT& message, CallbackFn&& func,
0056 FieldMask mask = FieldMask::kAll);
0057
0058 class ReflectionVisit final {
0059 public:
0060 template <typename MessageT, typename CallbackFn>
0061 static void VisitFields(MessageT& message, CallbackFn&& func, FieldMask mask);
0062
0063 template <typename CallbackFn>
0064 static void VisitMessageFields(const Message& message, CallbackFn&& func);
0065
0066 template <typename CallbackFn>
0067 static void VisitMessageFields(Message& message, CallbackFn&& func);
0068
0069 private:
0070 static const internal::ReflectionSchema& GetSchema(
0071 const Reflection* reflection) {
0072 return reflection->schema_;
0073 }
0074 static const Descriptor* GetDescriptor(const Reflection* reflection) {
0075 return reflection->descriptor_;
0076 }
0077 static const internal::ExtensionSet& ExtensionSet(
0078 const Reflection* reflection, const Message& message) {
0079 return reflection->GetExtensionSet(message);
0080 }
0081 static internal::ExtensionSet& ExtensionSet(const Reflection* reflection,
0082 Message& message) {
0083 return *reflection->MutableExtensionSet(&message);
0084 }
0085 };
0086
0087 inline bool ShouldVisit(FieldMask mask, FieldDescriptor::CppType cpptype) {
0088 if (PROTOBUF_PREDICT_TRUE(mask == FieldMask::kAll)) return true;
0089 return (static_cast<uint32_t>(mask) & (1 << cpptype)) != 0;
0090 }
0091
0092 template <typename MessageT, typename CallbackFn>
0093 void ReflectionVisit::VisitFields(MessageT& message, CallbackFn&& func,
0094 FieldMask mask) {
0095 const Reflection* reflection = message.GetReflection();
0096 const auto& schema = GetSchema(reflection);
0097
0098 ABSL_CHECK(!schema.HasWeakFields()) << "weak fields are not supported";
0099
0100
0101 const uint32_t* const has_bits =
0102 schema.HasHasbits() ? reflection->GetHasBits(message) : nullptr;
0103 const uint32_t* const has_bits_indices = schema.has_bit_indices_;
0104 const Descriptor* descriptor = GetDescriptor(reflection);
0105 const int field_count = descriptor->field_count();
0106
0107 for (int i = 0; i < field_count; i++) {
0108 const FieldDescriptor* field = descriptor->field(i);
0109 ABSL_DCHECK(!field->options().weak()) << "weak fields are not supported";
0110
0111 if (!ShouldVisit(mask, field->cpp_type())) continue;
0112
0113 if (field->is_repeated()) {
0114 switch (field->type()) {
0115 #define PROTOBUF_HANDLE_REPEATED_CASE(TYPE, CPPTYPE, NAME) \
0116 case FieldDescriptor::TYPE_##TYPE: { \
0117 ABSL_DCHECK(!field->is_map()); \
0118 const auto& rep = \
0119 reflection->GetRawNonOneof<RepeatedField<CPPTYPE>>(message, field); \
0120 if (rep.size() == 0) continue; \
0121 func(internal::Repeated##NAME##DynamicFieldInfo<MessageT>{ \
0122 reflection, message, field, rep}); \
0123 break; \
0124 }
0125
0126 PROTOBUF_HANDLE_REPEATED_CASE(DOUBLE, double, Double);
0127 PROTOBUF_HANDLE_REPEATED_CASE(FLOAT, float, Float);
0128 PROTOBUF_HANDLE_REPEATED_CASE(INT64, int64_t, Int64);
0129 PROTOBUF_HANDLE_REPEATED_CASE(UINT64, uint64_t, UInt64);
0130 PROTOBUF_HANDLE_REPEATED_CASE(INT32, int32_t, Int32);
0131 PROTOBUF_HANDLE_REPEATED_CASE(FIXED64, uint64_t, Fixed64);
0132 PROTOBUF_HANDLE_REPEATED_CASE(FIXED32, uint32_t, Fixed32);
0133 PROTOBUF_HANDLE_REPEATED_CASE(BOOL, bool, Bool);
0134 PROTOBUF_HANDLE_REPEATED_CASE(UINT32, uint32_t, UInt32);
0135 PROTOBUF_HANDLE_REPEATED_CASE(ENUM, int, Enum);
0136 PROTOBUF_HANDLE_REPEATED_CASE(SFIXED32, int32_t, SFixed32);
0137 PROTOBUF_HANDLE_REPEATED_CASE(SFIXED64, int64_t, SFixed64);
0138 PROTOBUF_HANDLE_REPEATED_CASE(SINT32, int32_t, SInt32);
0139 PROTOBUF_HANDLE_REPEATED_CASE(SINT64, int64_t, SInt64);
0140
0141 #define PROTOBUF_HANDLE_REPEATED_PTR_CASE(TYPE, CPPTYPE, NAME) \
0142 case FieldDescriptor::TYPE_##TYPE: { \
0143 if (PROTOBUF_PREDICT_TRUE(!field->is_map())) { \
0144 \
0145 const auto& rep = reflection->GetRawNonOneof<RepeatedPtrField<CPPTYPE>>( \
0146 message, field); \
0147 if (rep.size() == 0) continue; \
0148 func(internal::Repeated##NAME##DynamicFieldInfo<MessageT>{ \
0149 reflection, message, field, rep}); \
0150 } else { \
0151 \
0152 const auto& map = \
0153 reflection->GetRawNonOneof<MapFieldBase>(message, field); \
0154 if (map.size() == 0) continue; \
0155 const Descriptor* desc = field->message_type(); \
0156 func(internal::MapDynamicFieldInfo<MessageT>{reflection, message, field, \
0157 desc->map_key(), \
0158 desc->map_value(), map}); \
0159 } \
0160 break; \
0161 }
0162
0163 PROTOBUF_HANDLE_REPEATED_PTR_CASE(MESSAGE, Message, Message);
0164 PROTOBUF_HANDLE_REPEATED_PTR_CASE(GROUP, Message, Group);
0165
0166 case FieldDescriptor::TYPE_BYTES:
0167 case FieldDescriptor::TYPE_STRING:
0168 #define PROTOBUF_IMPL_STRING_CASE(CPPTYPE, NAME) \
0169 { \
0170 const auto& rep = \
0171 reflection->GetRawNonOneof<RepeatedPtrField<CPPTYPE>>(message, field); \
0172 if (rep.size() == 0) continue; \
0173 func(internal::Repeated##NAME##DynamicFieldInfo<MessageT>{ \
0174 reflection, message, field, rep}); \
0175 }
0176
0177 switch (cpp::EffectiveStringCType(field)) {
0178 default:
0179 case FieldOptions::STRING:
0180 PROTOBUF_IMPL_STRING_CASE(std::string, String);
0181 break;
0182 }
0183 break;
0184 default:
0185 internal::Unreachable();
0186 break;
0187 }
0188 #undef PROTOBUF_HANDLE_REPEATED_CASE
0189 #undef PROTOBUF_HANDLE_REPEATED_PTR_CASE
0190 #undef PROTOBUF_IMPL_STRING_CASE
0191 } else if (schema.InRealOneof(field)) {
0192 const OneofDescriptor* containing_oneof = field->containing_oneof();
0193 const uint32_t* const oneof_case_array =
0194 internal::GetConstPointerAtOffset<uint32_t>(
0195 &message, schema.oneof_case_offset_);
0196
0197 if (static_cast<int64_t>(oneof_case_array[containing_oneof->index()]) !=
0198 field->number()) {
0199 continue;
0200 }
0201 switch (field->type()) {
0202 #define PROTOBUF_HANDLE_CASE(TYPE, NAME) \
0203 case FieldDescriptor::TYPE_##TYPE: \
0204 func(internal::NAME##DynamicFieldInfo<MessageT, true>{reflection, message, \
0205 field}); \
0206 break;
0207 PROTOBUF_HANDLE_CASE(DOUBLE, Double);
0208 PROTOBUF_HANDLE_CASE(FLOAT, Float);
0209 PROTOBUF_HANDLE_CASE(INT64, Int64);
0210 PROTOBUF_HANDLE_CASE(UINT64, UInt64);
0211 PROTOBUF_HANDLE_CASE(INT32, Int32);
0212 PROTOBUF_HANDLE_CASE(FIXED64, Fixed64);
0213 PROTOBUF_HANDLE_CASE(FIXED32, Fixed32);
0214 PROTOBUF_HANDLE_CASE(BOOL, Bool);
0215 PROTOBUF_HANDLE_CASE(UINT32, UInt32);
0216 PROTOBUF_HANDLE_CASE(ENUM, Enum);
0217 PROTOBUF_HANDLE_CASE(SFIXED32, SFixed32);
0218 PROTOBUF_HANDLE_CASE(SFIXED64, SFixed64);
0219 PROTOBUF_HANDLE_CASE(SINT32, SInt32);
0220 PROTOBUF_HANDLE_CASE(SINT64, SInt64);
0221
0222 case FieldDescriptor::TYPE_MESSAGE:
0223 case FieldDescriptor::TYPE_GROUP:
0224 func(internal::MessageDynamicFieldInfo<MessageT, true>{
0225 reflection, message, field});
0226 break;
0227
0228 case FieldDescriptor::TYPE_BYTES:
0229 case FieldDescriptor::TYPE_STRING: {
0230 auto ctype = cpp::EffectiveStringCType(field);
0231 if (ctype == FieldOptions::CORD) {
0232 func(CordDynamicFieldInfo<MessageT, true>{reflection, message,
0233 field});
0234 } else {
0235 func(StringDynamicFieldInfo<MessageT, true>{reflection, message,
0236 field});
0237 }
0238 break;
0239 }
0240 default:
0241 internal::Unreachable();
0242 break;
0243 #undef PROTOBUF_HANDLE_CASE
0244 }
0245 } else {
0246 auto index = has_bits_indices[i];
0247 bool check_hasbits = has_bits && index != static_cast<uint32_t>(-1);
0248 if (PROTOBUF_PREDICT_TRUE(check_hasbits)) {
0249 if ((has_bits[index / 32] & (1u << (index % 32))) == 0) continue;
0250 } else {
0251
0252 if (!reflection->HasBit(message, field)) continue;
0253 }
0254 switch (field->type()) {
0255 #define PROTOBUF_HANDLE_CASE(TYPE, NAME) \
0256 case FieldDescriptor::TYPE_##TYPE: \
0257 func(internal::NAME##DynamicFieldInfo<MessageT, false>{reflection, \
0258 message, field}); \
0259 break;
0260 PROTOBUF_HANDLE_CASE(DOUBLE, Double);
0261 PROTOBUF_HANDLE_CASE(FLOAT, Float);
0262 PROTOBUF_HANDLE_CASE(INT64, Int64);
0263 PROTOBUF_HANDLE_CASE(UINT64, UInt64);
0264 PROTOBUF_HANDLE_CASE(INT32, Int32);
0265 PROTOBUF_HANDLE_CASE(FIXED64, Fixed64);
0266 PROTOBUF_HANDLE_CASE(FIXED32, Fixed32);
0267 PROTOBUF_HANDLE_CASE(BOOL, Bool);
0268 PROTOBUF_HANDLE_CASE(UINT32, UInt32);
0269 PROTOBUF_HANDLE_CASE(ENUM, Enum);
0270 PROTOBUF_HANDLE_CASE(SFIXED32, SFixed32);
0271 PROTOBUF_HANDLE_CASE(SFIXED64, SFixed64);
0272 PROTOBUF_HANDLE_CASE(SINT32, SInt32);
0273 PROTOBUF_HANDLE_CASE(SINT64, SInt64);
0274
0275 case FieldDescriptor::TYPE_MESSAGE:
0276 case FieldDescriptor::TYPE_GROUP:
0277 func(internal::MessageDynamicFieldInfo<MessageT, false>{
0278 reflection, message, field});
0279 break;
0280 case FieldDescriptor::TYPE_BYTES:
0281 case FieldDescriptor::TYPE_STRING: {
0282 auto ctype = cpp::EffectiveStringCType(field);
0283 if (ctype == FieldOptions::CORD) {
0284 func(CordDynamicFieldInfo<MessageT, false>{reflection, message,
0285 field});
0286 } else {
0287 func(StringDynamicFieldInfo<MessageT, false>{reflection, message,
0288 field});
0289 }
0290 break;
0291 }
0292 default:
0293 internal::Unreachable();
0294 break;
0295 #undef PROTOBUF_HANDLE_CASE
0296 }
0297 }
0298 }
0299
0300 if (!schema.HasExtensionSet()) return;
0301
0302 auto& set = ExtensionSet(reflection, message);
0303 auto* extendee = reflection->descriptor_;
0304 auto* pool = reflection->descriptor_pool_;
0305
0306 set.ForEach([&](int number, auto& ext) {
0307 ABSL_DCHECK_GT(ext.type, 0);
0308 ABSL_DCHECK_LE(ext.type, FieldDescriptor::MAX_TYPE);
0309
0310 if (!ShouldVisit(mask, FieldDescriptor::TypeToCppType(
0311 static_cast<FieldDescriptor::Type>(ext.type)))) {
0312 return;
0313 }
0314
0315 if (ext.is_repeated) {
0316 if (ext.GetSize() == 0) return;
0317
0318 switch (ext.type) {
0319 #define PROTOBUF_HANDLE_CASE(TYPE, NAME) \
0320 case FieldDescriptor::TYPE_##TYPE: \
0321 func(internal::Repeated##NAME##DynamicExtensionInfo<decltype(ext)>{ \
0322 ext, number}); \
0323 break;
0324 PROTOBUF_HANDLE_CASE(DOUBLE, Double);
0325 PROTOBUF_HANDLE_CASE(FLOAT, Float);
0326 PROTOBUF_HANDLE_CASE(INT64, Int64);
0327 PROTOBUF_HANDLE_CASE(UINT64, UInt64);
0328 PROTOBUF_HANDLE_CASE(INT32, Int32);
0329 PROTOBUF_HANDLE_CASE(FIXED64, Fixed64);
0330 PROTOBUF_HANDLE_CASE(FIXED32, Fixed32);
0331 PROTOBUF_HANDLE_CASE(BOOL, Bool);
0332 PROTOBUF_HANDLE_CASE(UINT32, UInt32);
0333 PROTOBUF_HANDLE_CASE(ENUM, Enum);
0334 PROTOBUF_HANDLE_CASE(SFIXED32, SFixed32);
0335 PROTOBUF_HANDLE_CASE(SFIXED64, SFixed64);
0336 PROTOBUF_HANDLE_CASE(SINT32, SInt32);
0337 PROTOBUF_HANDLE_CASE(SINT64, SInt64);
0338
0339 PROTOBUF_HANDLE_CASE(MESSAGE, Message);
0340 PROTOBUF_HANDLE_CASE(GROUP, Group);
0341
0342 case FieldDescriptor::TYPE_BYTES:
0343 case FieldDescriptor::TYPE_STRING:
0344 func(internal::RepeatedStringDynamicExtensionInfo<decltype(ext)>{
0345 ext, number});
0346 break;
0347 default:
0348 internal::Unreachable();
0349 break;
0350 #undef PROTOBUF_HANDLE_CASE
0351 }
0352 } else {
0353 if (ext.is_cleared) return;
0354
0355 switch (ext.type) {
0356 #define PROTOBUF_HANDLE_CASE(TYPE, NAME) \
0357 case FieldDescriptor::TYPE_##TYPE: \
0358 func(internal::NAME##DynamicExtensionInfo<decltype(ext)>{ext, number}); \
0359 break;
0360 PROTOBUF_HANDLE_CASE(DOUBLE, Double);
0361 PROTOBUF_HANDLE_CASE(FLOAT, Float);
0362 PROTOBUF_HANDLE_CASE(INT64, Int64);
0363 PROTOBUF_HANDLE_CASE(UINT64, UInt64);
0364 PROTOBUF_HANDLE_CASE(INT32, Int32);
0365 PROTOBUF_HANDLE_CASE(FIXED64, Fixed64);
0366 PROTOBUF_HANDLE_CASE(FIXED32, Fixed32);
0367 PROTOBUF_HANDLE_CASE(BOOL, Bool);
0368 PROTOBUF_HANDLE_CASE(UINT32, UInt32);
0369 PROTOBUF_HANDLE_CASE(ENUM, Enum);
0370 PROTOBUF_HANDLE_CASE(SFIXED32, SFixed32);
0371 PROTOBUF_HANDLE_CASE(SFIXED64, SFixed64);
0372 PROTOBUF_HANDLE_CASE(SINT32, SInt32);
0373 PROTOBUF_HANDLE_CASE(SINT64, SInt64);
0374
0375 PROTOBUF_HANDLE_CASE(GROUP, Group);
0376 case FieldDescriptor::TYPE_MESSAGE: {
0377 const FieldDescriptor* field =
0378 ext.descriptor != nullptr
0379 ? ext.descriptor
0380 : pool->FindExtensionByNumber(extendee, number);
0381 ABSL_DCHECK_EQ(field->number(), number);
0382 bool is_mset =
0383 field->containing_type()->options().message_set_wire_format();
0384 func(internal::MessageDynamicExtensionInfo<decltype(ext)>{ext, number,
0385 is_mset});
0386 break;
0387 }
0388
0389 case FieldDescriptor::TYPE_BYTES:
0390 case FieldDescriptor::TYPE_STRING:
0391 func(
0392 internal::StringDynamicExtensionInfo<decltype(ext)>{ext, number});
0393 break;
0394
0395 default:
0396 internal::Unreachable();
0397 break;
0398 #undef PROTOBUF_HANDLE_CASE
0399 }
0400 }
0401 });
0402 }
0403
0404 template <typename CallbackFn>
0405 void ReflectionVisit::VisitMessageFields(const Message& message,
0406 CallbackFn&& func) {
0407 ReflectionVisit::VisitFields(
0408 message,
0409 [&](auto info) {
0410 if constexpr (info.is_map) {
0411 auto value_type = info.value_type();
0412 if (value_type != FieldDescriptor::TYPE_MESSAGE &&
0413 value_type != FieldDescriptor::TYPE_GROUP) {
0414 return;
0415 }
0416 info.VisitElements([&](auto key, auto val) {
0417 if constexpr (val.cpp_type == FieldDescriptor::CPPTYPE_MESSAGE) {
0418 func(val.Get());
0419 }
0420 });
0421 } else if constexpr (info.cpp_type ==
0422 FieldDescriptor::CPPTYPE_MESSAGE) {
0423 if constexpr (info.is_repeated) {
0424 for (const auto& it : info.Get()) {
0425 func(DownCastMessage<Message>(it));
0426 }
0427 } else {
0428 func(info.Get());
0429 }
0430 }
0431 },
0432 FieldMask::kMessage);
0433 }
0434
0435 template <typename CallbackFn>
0436 void ReflectionVisit::VisitMessageFields(Message& message, CallbackFn&& func) {
0437 ReflectionVisit::VisitFields(
0438 message,
0439 [&](auto info) {
0440 if constexpr (info.is_map) {
0441 auto value_type = info.value_type();
0442 if (value_type != FieldDescriptor::TYPE_MESSAGE &&
0443 value_type != FieldDescriptor::TYPE_GROUP) {
0444 return;
0445 }
0446 info.VisitElements([&](auto key, auto val) {
0447 if constexpr (val.cpp_type == FieldDescriptor::CPPTYPE_MESSAGE) {
0448 func(*val.Mutable());
0449 }
0450 });
0451 } else if constexpr (info.cpp_type ==
0452 FieldDescriptor::CPPTYPE_MESSAGE) {
0453 if constexpr (info.is_repeated) {
0454 for (auto& it : info.Mutable()) {
0455 func(DownCastMessage<Message>(it));
0456 }
0457 } else {
0458 func(info.Mutable());
0459 }
0460 }
0461 },
0462 FieldMask::kMessage);
0463 }
0464
0465
0466
0467 template <typename MessageT, typename CallbackFn>
0468 void VisitFields(MessageT& message, CallbackFn&& func, FieldMask mask) {
0469 ReflectionVisit::VisitFields(message, std::forward<CallbackFn>(func), mask);
0470 }
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482 template <typename CallbackFn>
0483 void VisitMessageFields(const Message& message, CallbackFn&& func) {
0484 ReflectionVisit::VisitMessageFields(message, std::forward<CallbackFn>(func));
0485 }
0486
0487
0488
0489
0490 template <typename CallbackFn>
0491 void VisitMutableMessageFields(Message& message, CallbackFn&& func) {
0492 ReflectionVisit::VisitMessageFields(message, std::forward<CallbackFn>(func));
0493 }
0494
0495 #endif
0496
0497 }
0498 }
0499 }
0500
0501 #include "google/protobuf/port_undef.inc"
0502
0503 #endif