Add a helper for checking whether the descriptor pool has defaults for a particular language feature extension.

PiperOrigin-RevId: 703549414
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index 96130d1..575bb82 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -33,6 +33,7 @@
 #include <utility>
 #include <vector>
 
+#include "absl/algorithm/container.h"
 #include "absl/base/attributes.h"
 #include "absl/base/call_once.h"
 #include "absl/base/casts.h"
@@ -1102,20 +1103,6 @@
          allowed_proto3_extendees->end();
 }
 
-const FeatureSetDefaults& GetCppFeatureSetDefaults() {
-  static const FeatureSetDefaults* default_spec =
-      internal::OnShutdownDelete([] {
-        auto* defaults = new FeatureSetDefaults();
-        internal::ParseNoReflection(
-            absl::string_view{
-                PROTOBUF_INTERNAL_CPP_EDITION_DEFAULTS,
-                sizeof(PROTOBUF_INTERNAL_CPP_EDITION_DEFAULTS) - 1},
-            *defaults);
-        return defaults;
-      }());
-  return *default_spec;
-}
-
 template <typename ProtoT>
 void RestoreFeaturesToOptions(const FeatureSet* features, ProtoT* proto) {
   if (features != &FeatureSet::default_instance()) {
@@ -4789,6 +4776,36 @@
   return absl::OkStatus();
 }
 
+const FeatureSetDefaults& DescriptorPool::GetFeatureSetDefaults() const {
+  if (feature_set_defaults_spec_ != nullptr) return *feature_set_defaults_spec_;
+  static const FeatureSetDefaults* cpp_default_spec =
+      internal::OnShutdownDelete([] {
+        auto* defaults = new FeatureSetDefaults();
+        internal::ParseNoReflection(
+            absl::string_view{
+                PROTOBUF_INTERNAL_CPP_EDITION_DEFAULTS,
+                sizeof(PROTOBUF_INTERNAL_CPP_EDITION_DEFAULTS) - 1},
+            *defaults);
+        return defaults;
+      }());
+  return *cpp_default_spec;
+}
+
+bool DescriptorPool::ResolvesFeaturesForImpl(int extension_number) const {
+  for (const auto& edition_default : GetFeatureSetDefaults().defaults()) {
+    std::vector<const FieldDescriptor*> fields;
+    auto features = edition_default.fixed_features();
+    features.MergeFrom(edition_default.overridable_features());
+    features.GetReflection()->ListFields(features, &fields);
+    if (absl::c_find_if(fields, [&](const FieldDescriptor* field) {
+          return field->number() == extension_number;
+        }) == fields.end()) {
+      return false;
+    }
+  }
+  return true;
+}
+
 DescriptorBuilder::DescriptorBuilder(
     const DescriptorPool* pool, DescriptorPool::Tables* tables,
     DescriptorPool::DeferredValidation& deferred_validation,
@@ -5921,10 +5938,7 @@
     });
   }
 
-  const FeatureSetDefaults& defaults =
-      pool_->feature_set_defaults_spec_ == nullptr
-          ? GetCppFeatureSetDefaults()
-          : *pool_->feature_set_defaults_spec_;
+  const FeatureSetDefaults& defaults = pool_->GetFeatureSetDefaults();
 
   absl::StatusOr<FeatureResolver> feature_resolver =
       FeatureResolver::Create(file_->edition_, defaults);
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index d30a6ff..9e8bd68 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -2274,6 +2274,15 @@
   // be enforced while building proto files.
   absl::Status SetFeatureSetDefaults(FeatureSetDefaults spec);
 
+  // Returns true if the descriptor pool resolves features for the given
+  // extension.
+  template <typename TypeTraitsT, uint8_t field_type, bool is_packed>
+  bool ResolvesFeaturesFor(
+      const google::protobuf::internal::ExtensionIdentifier<
+          FeatureSet, TypeTraitsT, field_type, is_packed>& extension) const {
+    return ResolvesFeaturesForImpl(extension.number());
+  }
+
   // Toggles enforcement of extension declarations.
   // This enforcement is disabled by default because it requires full
   // descriptors with source-retention options, which are generally not
@@ -2525,6 +2534,10 @@
   bool IsReadyForCheckingDescriptorExtDecl(
       absl::string_view message_name) const;
 
+
+  bool ResolvesFeaturesForImpl(int extension_number) const;
+
+  const FeatureSetDefaults& GetFeatureSetDefaults() const;
 };
 
 
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index 17eddae..cdfc4c3 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -11678,6 +11678,24 @@
               )pb"));
 }
 
+TEST_F(DescriptorPoolFeaturesTest, ResolvesFeaturesForCppDefault) {
+  EXPECT_FALSE(pool_.ResolvesFeaturesFor(pb::test));
+  EXPECT_FALSE(pool_.ResolvesFeaturesFor(pb::TestMessage::test_message));
+  EXPECT_TRUE(pool_.ResolvesFeaturesFor(pb::cpp));  // The default.
+}
+
+TEST_F(DescriptorPoolFeaturesTest, ResolvesFeaturesFor) {
+  auto test_default_spec = FeatureResolver::CompileDefaults(
+      FeatureSet::descriptor(), {GetExtensionReflection(pb::test)},
+      EDITION_PROTO2, EDITION_99999_TEST_ONLY);
+  ASSERT_OK(test_default_spec);
+  ASSERT_OK(pool_.SetFeatureSetDefaults(std::move(test_default_spec).value()));
+
+  EXPECT_TRUE(pool_.ResolvesFeaturesFor(pb::test));
+  EXPECT_FALSE(pool_.ResolvesFeaturesFor(pb::TestMessage::test_message));
+  EXPECT_FALSE(pool_.ResolvesFeaturesFor(pb::cpp));
+}
+