Internal change

PiperOrigin-RevId: 969068444
diff --git a/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc b/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc
index 2849b27..b3d1b53 100644
--- a/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc
@@ -43,6 +43,9 @@
   auto enum_name = QualifiedClassName(field->enum_type(), opts);
   return {
       {"Enum", enum_name},
+      {"storage_type", field->real_containing_oneof() != nullptr
+                           ? "int"
+                           : EnumStorageTypeName(field->enum_type())},
       {"kDefault", Int32ToString(default_value->number())},
       Sub("assert_valid", is_open ? ""
                                   : absl::Substitute(
@@ -68,7 +71,7 @@
 
   void GeneratePrivateMembers(io::Printer* p) const override {
     p->Emit(R"cc(
-      int $name$_;
+      $storage_type$ $name$_;
     )cc");
   }
 
@@ -186,7 +189,7 @@
           clear_$oneof_name$();
           set_has_$name_internal$();
         }
-        $field_$ = value;
+        $field_$ = static_cast<$storage_type$>(value);
         $annotate_set$;
         // @@protoc_insertion_point(field_set:$pkg.Msg.field$)
       }
@@ -214,7 +217,7 @@
       inline void $Msg$::_internal_set_$name_internal$($Enum$ value) {
         $TsanDetectConcurrentMutation$;
         $assert_valid$;
-        $field_$ = value;
+        $field_$ = static_cast<$storage_type$>(value);
       }
     )cc");
   }
diff --git a/src/google/protobuf/compiler/cpp/file_unittest.cc b/src/google/protobuf/compiler/cpp/file_unittest.cc
index 0323494..2cf8bf7 100644
--- a/src/google/protobuf/compiler/cpp/file_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/file_unittest.cc
@@ -53,6 +53,9 @@
       "TestUnpackedTypes",
       "TestUnpackedExtensions",
       "TestString",
+      "TestShrunkenEnumSizes",
+      "TestShrunkenEnumPacking",
+      "TestShrunkenEnumOneof",
       "TestReservedFields",
       "TestRequiredOpenEnum",
       "TestRequiredOneof.NestedMessage",
diff --git a/src/google/protobuf/compiler/cpp/helpers.cc b/src/google/protobuf/compiler/cpp/helpers.cc
index a1b0229..c636d89 100644
--- a/src/google/protobuf/compiler/cpp/helpers.cc
+++ b/src/google/protobuf/compiler/cpp/helpers.cc
@@ -690,6 +690,50 @@
   return ResolveKeyword(enum_value->name());
 }
 
+int EstimateEnumSize(const EnumDescriptor* enum_desc) {
+  if (enum_desc == nullptr || enum_desc->value_count() == 0) return 4;
+  if (!enum_desc->is_closed()) return 4;
+  int min_val = enum_desc->value(0)->number();
+  int max_val = enum_desc->value(0)->number();
+  for (int i = 1; i < enum_desc->value_count(); ++i) {
+    int val = enum_desc->value(i)->number();
+    min_val = std::min(min_val, val);
+    max_val = std::max(max_val, val);
+  }
+  if ((min_val >= 0 && max_val <= std::numeric_limits<uint8_t>::max()) ||
+      (min_val >= std::numeric_limits<int8_t>::min() &&
+       max_val <= std::numeric_limits<int8_t>::max())) {
+    return 1;
+  }
+  if ((min_val >= 0 && max_val <= std::numeric_limits<uint16_t>::max()) ||
+      (min_val >= std::numeric_limits<int16_t>::min() &&
+       max_val <= std::numeric_limits<int16_t>::max())) {
+    return 2;
+  }
+  return 4;
+}
+
+bool IsEnumSigned(const EnumDescriptor* enum_desc) {
+  if (enum_desc == nullptr || enum_desc->value_count() == 0) return false;
+  for (int i = 0; i < enum_desc->value_count(); ++i) {
+    if (enum_desc->value(i)->number() < 0) return true;
+  }
+  return false;
+}
+
+const char* EnumStorageTypeName(const EnumDescriptor* enum_desc) {
+  if (enum_desc != nullptr && enum_desc->is_closed()) {
+    int size = EstimateEnumSize(enum_desc);
+    if (size == 1) {
+      return IsEnumSigned(enum_desc) ? "int8_t" : "uint8_t";
+    }
+    if (size == 2) {
+      return IsEnumSigned(enum_desc) ? "int16_t" : "uint16_t";
+    }
+  }
+  return "int";
+}
+
 int EstimateAlignmentSize(const FieldDescriptor* field) {
   if (field == nullptr) return 0;
   if (field->is_repeated()) return 8;
@@ -697,9 +741,11 @@
     case FieldDescriptor::CPPTYPE_BOOL:
       return 1;
 
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return EstimateEnumSize(field->enum_type());
+
     case FieldDescriptor::CPPTYPE_INT32:
     case FieldDescriptor::CPPTYPE_UINT32:
-    case FieldDescriptor::CPPTYPE_ENUM:
     case FieldDescriptor::CPPTYPE_FLOAT:
       return 4;
 
@@ -728,9 +774,11 @@
     case FieldDescriptor::CPPTYPE_BOOL:
       return 1;
 
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return EstimateEnumSize(field->enum_type());
+
     case FieldDescriptor::CPPTYPE_INT32:
     case FieldDescriptor::CPPTYPE_UINT32:
-    case FieldDescriptor::CPPTYPE_ENUM:
     case FieldDescriptor::CPPTYPE_FLOAT:
       return 4;
 
diff --git a/src/google/protobuf/compiler/cpp/helpers.h b/src/google/protobuf/compiler/cpp/helpers.h
index bf7e9de..ba13d0a 100644
--- a/src/google/protobuf/compiler/cpp/helpers.h
+++ b/src/google/protobuf/compiler/cpp/helpers.h
@@ -236,6 +236,17 @@
 // 64-bit pointers.
 int EstimateAlignmentSize(const FieldDescriptor* field);
 
+// Returns an estimate of the size/alignment for an enum based on its value
+// range. Returns 4 for open enums.
+int EstimateEnumSize(const EnumDescriptor* enum_desc);
+
+// Returns true if the enum has any negative values.
+bool IsEnumSigned(const EnumDescriptor* enum_desc);
+
+// Returns the C++ storage type name for a singular enum field (e.g. "uint8_t",
+// "int8_t", "uint16_t", "int16_t", or "int").
+const char* EnumStorageTypeName(const EnumDescriptor* enum_desc);
+
 // Returns an estimate of the size of the field.  This
 // can't guarantee to be correct because the generated code could be compiled on
 // different systems with different alignment rules.  The estimates below assume
diff --git a/src/google/protobuf/compiler/cpp/message.cc b/src/google/protobuf/compiler/cpp/message.cc
index ef21d5a..17d001d 100644
--- a/src/google/protobuf/compiler/cpp/message.cc
+++ b/src/google/protobuf/compiler/cpp/message.cc
@@ -1606,6 +1606,7 @@
           // clang-format on
         }}},
       R"cc(
+        // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
         struct Impl_ {
           //~ TODO: check if/when there is a need for an
           //~ outline dtor.
@@ -1635,6 +1636,7 @@
           //~ For detecting when concurrent accessor calls cause races.
           PROTOBUF_TSAN_DECLARE_MEMBER
         };
+        // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
         $union_impl$;
       )cc");
 
@@ -2585,6 +2587,21 @@
     if (ShouldSplit(field, options_)) {
       format(" | ::_pbi::kSplitFieldOffsetTag");
     }
+    if (field->type() == FieldDescriptor::TYPE_ENUM && !field->is_repeated() &&
+        !field->real_containing_oneof() && field->enum_type()->is_closed()) {
+      int size = EstimateEnumSize(field->enum_type());
+      if (size == 1) {
+        format(" | ::_pbi::kEnum8OffsetTag");
+        if (IsEnumSigned(field->enum_type())) {
+          format(" | ::_pbi::kEnumSignedOffsetTag");
+        }
+      } else if (size == 2) {
+        format(" | ::_pbi::kEnum16OffsetTag");
+        if (IsEnumSigned(field->enum_type())) {
+          format(" | ::_pbi::kEnumSignedOffsetTag");
+        }
+      }
+    }
     if (IsEagerlyVerifiedLazy(field, options_)) {
       format(" | ::_pbi::kLazyOffsetTag");
     } else if (IsStringInlined(field, options_)) {
diff --git a/src/google/protobuf/compiler/cpp/message_layout_helper.cc b/src/google/protobuf/compiler/cpp/message_layout_helper.cc
index fd77e8b..0324647 100644
--- a/src/google/protobuf/compiler/cpp/message_layout_helper.cc
+++ b/src/google/protobuf/compiler/cpp/message_layout_helper.cc
@@ -34,7 +34,7 @@
 
 auto FindIncompleteBlock(std::vector<FieldGroup>& aligned_to_8) {
   return absl::c_find_if(aligned_to_8, [](const FieldGroup& fg) {
-    return fg.estimated_memory_size() <= 4;
+    return fg.estimated_memory_size() < 8;
   });
 }
 
@@ -165,6 +165,10 @@
         field_alignment_groups.aligned_to_1[f][FieldHotnessIndex(hotness)]
             .push_back(fg);
         break;
+      case 2:
+        field_alignment_groups.aligned_to_2[f][FieldHotnessIndex(hotness)]
+            .push_back(fg);
+        break;
       case 4:
         field_alignment_groups.aligned_to_4[f][FieldHotnessIndex(hotness)]
             .push_back(fg);
@@ -189,16 +193,26 @@
   // For each family, group fields to optimize locality and padding.
   for (size_t f = 0; f < kMaxFamily; ++f) {
     auto& aligned_to_1 = field_alignment_groups.aligned_to_1[f];
+    auto& aligned_to_2 = field_alignment_groups.aligned_to_2[f];
     auto& aligned_to_4 = field_alignment_groups.aligned_to_4[f];
     auto& aligned_to_8 = field_alignment_groups.aligned_to_8[f];
 
-    // Group single-byte fields into groups of 4 bytes and combine them with the
-    // existing 4-byte groups.
-    auto aligned_1_to_4 = ConsolidateAlignedFieldGroups(
-        aligned_to_1, /*alignment=*/1, /*target_alignment=*/4);
+    // Group single-byte fields into groups of 2 bytes and combine them with the
+    // existing 2-byte groups.
+    auto aligned_1_to_2 = ConsolidateAlignedFieldGroups(
+        aligned_to_1, /*alignment=*/1, /*target_alignment=*/2);
     for (size_t h = 0; h < kMaxHotness; ++h) {
-      aligned_to_4[h].insert(aligned_to_4[h].end(), aligned_1_to_4[h].begin(),
-                             aligned_1_to_4[h].end());
+      aligned_to_2[h].insert(aligned_to_2[h].end(), aligned_1_to_2[h].begin(),
+                             aligned_1_to_2[h].end());
+    }
+
+    // Group 2-byte fields into groups of 4 bytes and combine them with the
+    // existing 4-byte groups.
+    auto aligned_2_to_4 = ConsolidateAlignedFieldGroups(
+        aligned_to_2, /*alignment=*/2, /*target_alignment=*/4);
+    for (size_t h = 0; h < kMaxHotness; ++h) {
+      aligned_to_4[h].insert(aligned_to_4[h].end(), aligned_2_to_4[h].begin(),
+                             aligned_2_to_4[h].end());
     }
 
     // Group 4-byte fields into groups of 8 bytes and combine them with the
@@ -295,7 +309,7 @@
   for (size_t h = 0; h < kMaxHotness; ++h) {
     auto& partition = field_groups[h];
     auto& target_partition = partitions_aligned_to_target[h];
-    target_partition.reserve((field_groups.size() + size_inflation - 1) /
+    target_partition.reserve((partition.size() + size_inflation - 1) /
                              size_inflation);
 
     // Using stable_sort ensures that the output is consistent across runs.
diff --git a/src/google/protobuf/compiler/cpp/message_layout_helper.h b/src/google/protobuf/compiler/cpp/message_layout_helper.h
index 4a26ea5..00a723f 100644
--- a/src/google/protobuf/compiler/cpp/message_layout_helper.h
+++ b/src/google/protobuf/compiler/cpp/message_layout_helper.h
@@ -165,6 +165,7 @@
 
   struct FieldAlignmentGroups {
     FieldPartitionArray aligned_to_1;
+    FieldPartitionArray aligned_to_2;
     FieldPartitionArray aligned_to_4;
     FieldPartitionArray aligned_to_8;
   };
@@ -199,7 +200,7 @@
       const std::vector<internal::TailCallTableInfo::FastFieldInfo>&
           fast_path_fields);
 
-  // Groups fields into alignment equivalence classes (1, 4, and 8). Within
+  // Groups fields into alignment equivalence classes (1, 2, 4, and 8). Within
   // each alignment equivalence class, fields are partitioned by `FieldFamily`
   // and `FieldHotness`.
   FieldAlignmentGroups BuildFieldAlignmentGroups(const FieldVector& fields,
diff --git a/src/google/protobuf/compiler/cpp/message_layout_helper_unittest.cc b/src/google/protobuf/compiler/cpp/message_layout_helper_unittest.cc
new file mode 100644
index 0000000..7aa3700
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/message_layout_helper_unittest.cc
@@ -0,0 +1,221 @@
+#include <cstddef>
+#include <string>
+#include <vector>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include "google/protobuf/compiler/cpp/options.h"
+#include "google/protobuf/compiler/cpp/padding_optimizer.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/test_textproto.h"
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+namespace {
+
+using ::testing::ElementsAre;
+
+std::vector<std::string> GetOptimizedFieldNames(const Descriptor* descriptor) {
+  PaddingOptimizer optimizer(descriptor);
+  std::vector<const FieldDescriptor*> fields;
+  fields.reserve(static_cast<size_t>(descriptor->field_count()));
+  for (int i = 0; i < descriptor->field_count(); ++i) {
+    fields.push_back(descriptor->field(i));
+  }
+  Options options;
+  auto optimized = optimizer.OptimizeLayout(fields, options);
+  std::vector<std::string> names;
+  names.reserve(optimized.size());
+  for (const auto* field : optimized) {
+    names.push_back(std::string(field->name()));
+  }
+  return names;
+}
+
+TEST(MessageLayoutHelperTest, TwoByteFieldAlignmentAndPairing) {
+  FileDescriptorProto file_proto = ParseTextOrDie(R"pb(
+    name: "two_byte_test.proto"
+    syntax: "proto2"
+    enum_type {
+      name: "Enum2Byte"
+      value { name: "E2_A" number: 0 }
+      value { name: "E2_B" number: 1000 }
+    }
+    message_type {
+      name: "Test2ByteMessage"
+      field { name: "int64_1" number: 1 type: TYPE_INT64 }
+      field {
+        name: "enum2_1"
+        number: 2
+        type: TYPE_ENUM
+        type_name: ".Enum2Byte"
+      }
+      field {
+        name: "enum2_2"
+        number: 3
+        type: TYPE_ENUM
+        type_name: ".Enum2Byte"
+      }
+      field { name: "int32_1" number: 4 type: TYPE_INT32 }
+    }
+  )pb");
+
+  DescriptorPool pool;
+  const FileDescriptor* file = pool.BuildFile(file_proto);
+  ASSERT_NE(file, nullptr);
+
+  const Descriptor* message = file->FindMessageTypeByName("Test2ByteMessage");
+  ASSERT_NE(message, nullptr);
+
+  // enum2_1 (2B) and enum2_2 (2B) consolidate into a 4B group.
+  // The 4B group and int32_1 (4B) consolidate into an 8B group.
+  // int64_1 is in the 8B group.
+  EXPECT_THAT(GetOptimizedFieldNames(message),
+              ElementsAre("int64_1", "enum2_1", "enum2_2", "int32_1"));
+}
+
+TEST(MessageLayoutHelperTest, HierarchicalConsolidation1To2To4To8) {
+  FileDescriptorProto file_proto = ParseTextOrDie(R"pb(
+    name: "hierarchical_test.proto"
+    syntax: "proto2"
+    enum_type {
+      name: "Enum2Byte"
+      value { name: "E2_A" number: 0 }
+      value { name: "E2_B" number: 1000 }
+    }
+    message_type {
+      name: "TestHierarchyMessage"
+      field { name: "int64_1" number: 1 type: TYPE_INT64 }
+      field { name: "bool_1" number: 2 type: TYPE_BOOL }
+      field { name: "bool_2" number: 3 type: TYPE_BOOL }
+      field {
+        name: "enum2_1"
+        number: 4
+        type: TYPE_ENUM
+        type_name: ".Enum2Byte"
+      }
+      field { name: "int32_1" number: 5 type: TYPE_INT32 }
+    }
+  )pb");
+
+  DescriptorPool pool;
+  const FileDescriptor* file = pool.BuildFile(file_proto);
+  ASSERT_NE(file, nullptr);
+
+  const Descriptor* message =
+      file->FindMessageTypeByName("TestHierarchyMessage");
+  ASSERT_NE(message, nullptr);
+
+  // 1 -> 2: bool_1 (1B) + bool_2 (1B) -> 2B group
+  // 2 -> 4: {bool_1, bool_2} (2B) + enum2_1 (2B) -> 4B group
+  // 4 -> 8: {bool_1, bool_2, enum2_1} (4B) + int32_1 (4B) -> 8B group
+  // 8B group and int64_1 (8B) form the message with 0 padding overhead.
+  EXPECT_THAT(GetOptimizedFieldNames(message),
+              ElementsAre("int64_1", "bool_1", "bool_2", "enum2_1", "int32_1"));
+}
+
+TEST(MessageLayoutHelperTest,
+     PaddingOptimizationAcrossFamiliesWith2ByteLeftovers) {
+  FileDescriptorProto file_proto = ParseTextOrDie(R"pb(
+    name: "family_padding_test.proto"
+    syntax: "proto2"
+    enum_type {
+      name: "Enum2Byte"
+      value { name: "E2_ZERO" number: 0 }
+      value { name: "E2_VAL" number: 1000 }
+    }
+    message_type {
+      name: "TestFamilyPaddingMessage"
+      # ZERO_INITIALIZABLE family
+      field { name: "z_int64" number: 1 type: TYPE_INT64 }
+      field {
+        name: "z_enum2"
+        number: 2
+        type: TYPE_ENUM
+        type_name: ".Enum2Byte"
+        default_value: "E2_ZERO"
+      }
+      # OTHER family (custom defaults)
+      field {
+        name: "o_enum2"
+        number: 3
+        type: TYPE_ENUM
+        type_name: ".Enum2Byte"
+        default_value: "E2_VAL"
+      }
+      field { name: "o_int32" number: 4 type: TYPE_INT32 default_value: "100" }
+      field { name: "o_int64" number: 5 type: TYPE_INT64 default_value: "100" }
+    }
+  )pb");
+
+  DescriptorPool pool;
+  const FileDescriptor* file = pool.BuildFile(file_proto);
+  ASSERT_NE(file, nullptr);
+
+  const Descriptor* message =
+      file->FindMessageTypeByName("TestFamilyPaddingMessage");
+  ASSERT_NE(message, nullptr);
+
+  // In ZERO_INITIALIZABLE: z_int64 is 8B. z_enum2 is an incomplete 2B block.
+  // z_enum2 is moved to the end of ZERO_INITIALIZABLE.
+  // In OTHER: o_enum2 (2B) + o_int32 (4B) = 6B (incomplete block < 8B).
+  // The incomplete 6B block {o_enum2, o_int32} is hoisted to the beginning of
+  // OTHER. Thus, z_enum2 (2B) and {o_enum2, o_int32} (6B) meet at the boundary
+  // to form an 8B block!
+  EXPECT_THAT(
+      GetOptimizedFieldNames(message),
+      ElementsAre("z_int64", "z_enum2", "o_enum2", "o_int32", "o_int64"));
+}
+
+TEST(MessageLayoutHelperTest, MultipleMixedSizesConsolidation) {
+  FileDescriptorProto file_proto = ParseTextOrDie(R"pb(
+    name: "mixed_sizes_test.proto"
+    syntax: "proto2"
+    enum_type {
+      name: "Enum1Byte"
+      value { name: "E1_A" number: 0 }
+      value { name: "E1_B" number: 10 }
+    }
+    enum_type {
+      name: "Enum2Byte"
+      value { name: "E2_A" number: 0 }
+      value { name: "E2_B" number: 500 }
+    }
+    enum_type {
+      name: "Enum4Byte"
+      value { name: "E4_A" number: 0 }
+      value { name: "E4_B" number: 100000 }
+    }
+    message_type {
+      name: "TestMixedSizesMessage"
+      field { name: "i64" number: 1 type: TYPE_INT64 }
+      field { name: "b1" number: 2 type: TYPE_BOOL }
+      field { name: "e1" number: 3 type: TYPE_ENUM type_name: ".Enum1Byte" }
+      field { name: "e2" number: 4 type: TYPE_ENUM type_name: ".Enum2Byte" }
+      field { name: "e4" number: 5 type: TYPE_ENUM type_name: ".Enum4Byte" }
+    }
+  )pb");
+
+  DescriptorPool pool;
+  const FileDescriptor* file = pool.BuildFile(file_proto);
+  ASSERT_NE(file, nullptr);
+
+  const Descriptor* message =
+      file->FindMessageTypeByName("TestMixedSizesMessage");
+  ASSERT_NE(message, nullptr);
+
+  // b1 (1B) + e1 (1B) -> 2B
+  // {b1, e1} (2B) + e2 (2B) -> 4B
+  // {b1, e1, e2} (4B) + e4 (4B) -> 8B
+  // i64 (8B) + {b1, e1, e2, e4} (8B)
+  EXPECT_THAT(GetOptimizedFieldNames(message),
+              ElementsAre("i64", "b1", "e1", "e2", "e4"));
+}
+
+}  // namespace
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/cpp/message_size_unittest.cc b/src/google/protobuf/compiler/cpp/message_size_unittest.cc
index c2fe3ec..c15d3bb 100644
--- a/src/google/protobuf/compiler/cpp/message_size_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/message_size_unittest.cc
@@ -425,6 +425,35 @@
   EXPECT_EQ(sizeof(proto2_unittest::TestPackedTypes), sizeof(T));
 }
 
+TEST(GeneratedMessageTest, ShrunkenEnumPackingSize) {
+  struct MockGenerated : public MockMessageBase {  // 16 bytes
+    int has_bits[1];                               // 4 bytes
+    int cached_size;                               // 4 bytes
+    uint8_t e1;                                    // 1 byte
+    int8_t e2;                                     // 1 byte
+    uint16_t e3;                                   // 2 bytes
+    bool b1;                                       // 1 byte
+    bool b2;                                       // 1 byte
+    bool b3;                                       // 1 byte
+    bool b4;                                       // 1 byte
+    PROTOBUF_TSAN_DECLARE_MEMBER;                  // 0-4 bytes
+    // + padding
+  };
+  ABSL_CHECK_MESSAGE_SIZE(MockGenerated, 32);
+
+  struct MockSplitGenerated : public MockMessageBase {  // 16 bytes
+    int has_bits[1];                                    // 4 bytes
+    int cached_size;               // 4 bytes + 4 bytes padding
+    void* split;                   // 8 bytes
+    PROTOBUF_TSAN_DECLARE_MEMBER;  // 0-4 bytes
+  };
+  ABSL_CHECK_MESSAGE_SIZE(MockSplitGenerated, 32);
+
+  using T = std::conditional_t<internal::ForceSplitFieldsInProtoc(),
+                               MockSplitGenerated, MockGenerated>;
+  EXPECT_EQ(sizeof(proto2_unittest::TestShrunkenEnumPacking), sizeof(T));
+}
+
 }  // namespace cpp_unittest
 }  // namespace cpp
 }  // namespace compiler
diff --git a/src/google/protobuf/compiler/cpp/parse_function_generator.cc b/src/google/protobuf/compiler/cpp/parse_function_generator.cc
index b479a18..7884eb4 100644
--- a/src/google/protobuf/compiler/cpp/parse_function_generator.cc
+++ b/src/google/protobuf/compiler/cpp/parse_function_generator.cc
@@ -98,6 +98,17 @@
       return std::monostate{};
     };
 
+    const auto enum_rep = [&]() -> TailCallTableInfo::FieldOptions::EnumRep {
+      if (field->type() == FieldDescriptor::TYPE_ENUM &&
+          !field->is_repeated() && !field->real_containing_oneof() &&
+          field->enum_type()->is_closed()) {
+        int size = EstimateEnumSize(field->enum_type());
+        if (size == 1) return TailCallTableInfo::FieldOptions::kEnum8;
+        if (size == 2) return TailCallTableInfo::FieldOptions::kEnum16;
+      }
+      return TailCallTableInfo::FieldOptions::kEnum32;
+    };
+
     fields.push_back({
         field,
         hasbit_index.value_or(internal::kNoHasbit),
@@ -108,6 +119,7 @@
         /* use_direct_tcparser_table */ true,
         ShouldSplit(field, options),
         str_options(),
+        enum_rep(),
     });
   }
   return fields;
diff --git a/src/google/protobuf/compiler/cpp/unittest.inc b/src/google/protobuf/compiler/cpp/unittest.inc
index 056855d..8e7b127 100644
--- a/src/google/protobuf/compiler/cpp/unittest.inc
+++ b/src/google/protobuf/compiler/cpp/unittest.inc
@@ -22,10 +22,12 @@
 // correctly and produces the interfaces we expect, which is why this test
 // is written this way.
 
+#include <atomic>
 #include <cstdint>
 #include <functional>
 #include <limits>
 #include <memory>
+#include <thread>
 #include <vector>
 
 #include "absl/base/attributes.h"
@@ -2195,8 +2197,271 @@
   EXPECT_EQ("Foo", file->service(0)->method(0)->name());
 }
 
+#ifndef UNITTEST_PROFILE_DRIVEN
+TEST(GENERATED_MESSAGE_TEST_NAME, ShrunkenEnumReflection) {
+  UNITTEST::TestShrunkenEnumSizes message1;
+  const Reflection* ref = message1.GetReflection();
+  const Descriptor* desc = message1.GetDescriptor();
+
+  const FieldDescriptor* f_e1_u = desc->FindFieldByName("enum1_u");
+  const FieldDescriptor* f_e1_s = desc->FindFieldByName("enum1_s");
+  const FieldDescriptor* f_e2_u = desc->FindFieldByName("enum2_u");
+  const FieldDescriptor* f_e2_s = desc->FindFieldByName("enum2_s");
+  const FieldDescriptor* f_e4 = desc->FindFieldByName("enum4");
+  const FieldDescriptor* f_flag = desc->FindFieldByName("flag");
+  const FieldDescriptor* f_small_int = desc->FindFieldByName("small_int");
+
+  ASSERT_NE(f_e1_u, nullptr);
+  ASSERT_NE(f_e1_s, nullptr);
+  ASSERT_NE(f_e2_u, nullptr);
+  ASSERT_NE(f_e2_s, nullptr);
+  ASSERT_NE(f_e4, nullptr);
+  ASSERT_NE(f_flag, nullptr);
+  ASSERT_NE(f_small_int, nullptr);
+
+  // SetEnumValue
+  ref->SetEnumValue(&message1, f_e1_u, UNITTEST::ENUM1_U_MAX);
+  ref->SetEnumValue(&message1, f_e1_s, UNITTEST::ENUM1_S_MIN);
+  ref->SetEnumValue(&message1, f_e2_u, UNITTEST::ENUM2_U_MAX);
+  ref->SetEnumValue(&message1, f_e2_s, UNITTEST::ENUM2_S_MIN);
+  ref->SetEnumValue(&message1, f_e4, UNITTEST::ENUM4_MAX);
+  ref->SetBool(&message1, f_flag, true);
+  ref->SetInt32(&message1, f_small_int, 42);
+
+  // GetEnumValue
+  EXPECT_EQ(ref->GetEnumValue(message1, f_e1_u), UNITTEST::ENUM1_U_MAX);
+  EXPECT_EQ(ref->GetEnumValue(message1, f_e1_s), UNITTEST::ENUM1_S_MIN);
+  EXPECT_EQ(ref->GetEnumValue(message1, f_e2_u), UNITTEST::ENUM2_U_MAX);
+  EXPECT_EQ(ref->GetEnumValue(message1, f_e2_s), UNITTEST::ENUM2_S_MIN);
+  EXPECT_EQ(ref->GetEnumValue(message1, f_e4), UNITTEST::ENUM4_MAX);
+  EXPECT_EQ(ref->GetBool(message1, f_flag), true);
+  EXPECT_EQ(ref->GetInt32(message1, f_small_int), 42);
+
+  // Verify direct getters match reflection
+  EXPECT_EQ(message1.enum1_u(), UNITTEST::ENUM1_U_MAX);
+  EXPECT_EQ(message1.enum1_s(), UNITTEST::ENUM1_S_MIN);
+  EXPECT_EQ(message1.enum2_u(), UNITTEST::ENUM2_U_MAX);
+  EXPECT_EQ(message1.enum2_s(), UNITTEST::ENUM2_S_MIN);
+  EXPECT_EQ(message1.enum4(), UNITTEST::ENUM4_MAX);
+
+  // Test CopyFrom
+  UNITTEST::TestShrunkenEnumSizes message2;
+  message2.CopyFrom(message1);
+  EXPECT_EQ(message2.enum1_u(), UNITTEST::ENUM1_U_MAX);
+  EXPECT_EQ(message2.enum1_s(), UNITTEST::ENUM1_S_MIN);
+  EXPECT_EQ(message2.enum2_u(), UNITTEST::ENUM2_U_MAX);
+  EXPECT_EQ(message2.enum2_s(), UNITTEST::ENUM2_S_MIN);
+  EXPECT_EQ(message2.enum4(), UNITTEST::ENUM4_MAX);
+
+  // Test Swap
+  UNITTEST::TestShrunkenEnumSizes message3;
+  message3.set_enum1_u(UNITTEST::ENUM1_U_ONE);
+  message3.set_enum1_s(UNITTEST::ENUM1_S_MAX);
+  message3.set_enum2_u(UNITTEST::ENUM2_U_ONE);
+  message3.set_enum2_s(UNITTEST::ENUM2_S_MAX);
+  message3.set_enum4(UNITTEST::ENUM4_ONE);
+
+  message1.Swap(&message3);
+  EXPECT_EQ(message1.enum1_u(), UNITTEST::ENUM1_U_ONE);
+  EXPECT_EQ(message1.enum1_s(), UNITTEST::ENUM1_S_MAX);
+  EXPECT_EQ(message1.enum2_u(), UNITTEST::ENUM2_U_ONE);
+  EXPECT_EQ(message1.enum2_s(), UNITTEST::ENUM2_S_MAX);
+  EXPECT_EQ(message1.enum4(), UNITTEST::ENUM4_ONE);
+
+  EXPECT_EQ(message3.enum1_u(), UNITTEST::ENUM1_U_MAX);
+  EXPECT_EQ(message3.enum1_s(), UNITTEST::ENUM1_S_MIN);
+  EXPECT_EQ(message3.enum2_u(), UNITTEST::ENUM2_U_MAX);
+  EXPECT_EQ(message3.enum2_s(), UNITTEST::ENUM2_S_MIN);
+  EXPECT_EQ(message3.enum4(), UNITTEST::ENUM4_MAX);
+
+  // Test Reflection::ClearField
+  ref->ClearField(&message1, f_e1_u);
+  ref->ClearField(&message1, f_e1_s);
+  ref->ClearField(&message1, f_e2_u);
+  ref->ClearField(&message1, f_e2_s);
+  ref->ClearField(&message1, f_e4);
+  EXPECT_EQ(message1.enum1_u(), UNITTEST::ENUM1_U_UNSPECIFIED);
+  EXPECT_EQ(message1.enum1_s(), UNITTEST::ENUM1_S_UNSPECIFIED);
+  EXPECT_EQ(message1.enum2_u(), UNITTEST::ENUM2_U_UNSPECIFIED);
+  EXPECT_EQ(message1.enum2_s(), UNITTEST::ENUM2_S_UNSPECIFIED);
+  EXPECT_EQ(message1.enum4(), UNITTEST::ENUM4_UNSPECIFIED);
+}
+#endif  // !UNITTEST_PROFILE_DRIVEN
+
 #endif  // !PROTOBUF_TEST_NO_DESCRIPTORS
 
+#ifndef UNITTEST_PROFILE_DRIVEN
+TEST(GENERATED_MESSAGE_TEST_NAME, ShrunkenEnumSizeReduction) {
+  // TestShrunkenEnumPacking has 7 fields: e1(1B), e2(1B), e3(2B), b1(1B),
+  // b2(1B), b3(1B), b4(1B). All 7 fields fit in exactly 8 bytes of struct
+  // payload. With 32-bit enums, 3 enums (12B) + 4 bools (4B) = 16 bytes.
+  EXPECT_LE(sizeof(UNITTEST::TestShrunkenEnumPacking),
+            sizeof(internal::ZeroFieldsBase) + 4 + 8 + sizeof(void*));
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ShrunkenEnumAccessorsAndDefaults) {
+  UNITTEST::TestShrunkenEnumSizes message;
+  // Check default values (first defined enum value)
+  EXPECT_EQ(message.enum1_u(), UNITTEST::ENUM1_U_UNSPECIFIED);
+  EXPECT_EQ(message.enum1_s(), UNITTEST::ENUM1_S_UNSPECIFIED);
+  EXPECT_EQ(message.enum2_u(), UNITTEST::ENUM2_U_UNSPECIFIED);
+  EXPECT_EQ(message.enum2_s(), UNITTEST::ENUM2_S_UNSPECIFIED);
+  EXPECT_EQ(message.enum4(), UNITTEST::ENUM4_UNSPECIFIED);
+
+  // Check setting values
+  message.set_enum1_u(UNITTEST::ENUM1_U_MAX);
+  message.set_enum1_s(UNITTEST::ENUM1_S_MAX);
+  message.set_enum2_u(UNITTEST::ENUM2_U_MAX);
+  message.set_enum2_s(UNITTEST::ENUM2_S_MAX);
+  message.set_enum4(UNITTEST::ENUM4_MAX);
+  message.set_flag(true);
+  message.set_small_int(12345);
+
+  EXPECT_EQ(message.enum1_u(), UNITTEST::ENUM1_U_MAX);
+  EXPECT_EQ(message.enum1_s(), UNITTEST::ENUM1_S_MAX);
+  EXPECT_EQ(message.enum2_u(), UNITTEST::ENUM2_U_MAX);
+  EXPECT_EQ(message.enum2_s(), UNITTEST::ENUM2_S_MAX);
+  EXPECT_EQ(message.enum4(), UNITTEST::ENUM4_MAX);
+  EXPECT_EQ(message.flag(), true);
+  EXPECT_EQ(message.small_int(), 12345);
+
+  // Check clear
+  message.clear_enum1_u();
+  message.clear_enum1_s();
+  message.clear_enum2_u();
+  message.clear_enum2_s();
+  message.clear_enum4();
+  EXPECT_EQ(message.enum1_u(), UNITTEST::ENUM1_U_UNSPECIFIED);
+  EXPECT_EQ(message.enum1_s(), UNITTEST::ENUM1_S_UNSPECIFIED);
+  EXPECT_EQ(message.enum2_u(), UNITTEST::ENUM2_U_UNSPECIFIED);
+  EXPECT_EQ(message.enum2_s(), UNITTEST::ENUM2_S_UNSPECIFIED);
+  EXPECT_EQ(message.enum4(), UNITTEST::ENUM4_UNSPECIFIED);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ShrunkenEnumSerializationAndParsing) {
+  UNITTEST::TestShrunkenEnumSizes message1;
+  message1.set_enum1_u(UNITTEST::ENUM1_U_MAX);
+  message1.set_enum1_s(UNITTEST::ENUM1_S_MAX);
+  message1.set_enum2_u(UNITTEST::ENUM2_U_MAX);
+  message1.set_enum2_s(UNITTEST::ENUM2_S_MAX);
+  message1.set_enum4(UNITTEST::ENUM4_MAX);
+  message1.set_flag(true);
+  message1.set_small_int(99999);
+
+  std::string data = message1.SerializeAsString();
+
+  // Parse via TcTable fast parser
+  UNITTEST::TestShrunkenEnumSizes message2;
+  EXPECT_TRUE(message2.ParseFromString(data));
+  EXPECT_EQ(message2.enum1_u(), UNITTEST::ENUM1_U_MAX);
+  EXPECT_EQ(message2.enum1_s(), UNITTEST::ENUM1_S_MAX);
+  EXPECT_EQ(message2.enum2_u(), UNITTEST::ENUM2_U_MAX);
+  EXPECT_EQ(message2.enum2_s(), UNITTEST::ENUM2_S_MAX);
+  EXPECT_EQ(message2.enum4(), UNITTEST::ENUM4_MAX);
+  EXPECT_EQ(message2.flag(), true);
+  EXPECT_EQ(message2.small_int(), 99999);
+
+  // Test negative values on signed enums
+  message1.set_enum1_s(UNITTEST::ENUM1_S_MIN);
+  message1.set_enum2_s(UNITTEST::ENUM2_S_MIN);
+  data = message1.SerializeAsString();
+
+  UNITTEST::TestShrunkenEnumSizes message3;
+  EXPECT_TRUE(message3.ParseFromString(data));
+  EXPECT_EQ(message3.enum1_s(), UNITTEST::ENUM1_S_MIN);
+  EXPECT_EQ(message3.enum2_s(), UNITTEST::ENUM2_S_MIN);
+
+  // Parse via stream (fallback miniparse)
+  UNITTEST::TestShrunkenEnumSizes message4;
+  io::ArrayInputStream array_stream(data.data(), static_cast<int>(data.size()));
+  io::CodedInputStream coded_stream(&array_stream);
+  EXPECT_TRUE(message4.ParseFromCodedStream(&coded_stream));
+  EXPECT_EQ(message4.enum1_s(), UNITTEST::ENUM1_S_MIN);
+  EXPECT_EQ(message4.enum2_s(), UNITTEST::ENUM2_S_MIN);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ShrunkenEnumOneof) {
+  UNITTEST::TestShrunkenEnumOneof message;
+  EXPECT_EQ(message.foo_case(), UNITTEST::TestShrunkenEnumOneof::FOO_NOT_SET);
+
+  message.set_e1_u(UNITTEST::ENUM1_U_MAX);
+  EXPECT_EQ(message.foo_case(), UNITTEST::TestShrunkenEnumOneof::kE1U);
+  EXPECT_EQ(message.e1_u(), UNITTEST::ENUM1_U_MAX);
+
+  message.set_e1_s(UNITTEST::ENUM1_S_MIN);
+  EXPECT_EQ(message.foo_case(), UNITTEST::TestShrunkenEnumOneof::kE1S);
+  EXPECT_EQ(message.e1_s(), UNITTEST::ENUM1_S_MIN);
+
+  message.set_e2_u(UNITTEST::ENUM2_U_MAX);
+  EXPECT_EQ(message.foo_case(), UNITTEST::TestShrunkenEnumOneof::kE2U);
+  EXPECT_EQ(message.e2_u(), UNITTEST::ENUM2_U_MAX);
+
+  message.set_e2_s(UNITTEST::ENUM2_S_MIN);
+  EXPECT_EQ(message.foo_case(), UNITTEST::TestShrunkenEnumOneof::kE2S);
+  EXPECT_EQ(message.e2_s(), UNITTEST::ENUM2_S_MIN);
+
+  std::string data = message.SerializeAsString();
+  UNITTEST::TestShrunkenEnumOneof parsed;
+  EXPECT_TRUE(parsed.ParseFromString(data));
+  EXPECT_EQ(parsed.foo_case(), UNITTEST::TestShrunkenEnumOneof::kE2S);
+  EXPECT_EQ(parsed.e2_s(), UNITTEST::ENUM2_S_MIN);
+
+  message.clear_foo();
+  EXPECT_EQ(message.foo_case(), UNITTEST::TestShrunkenEnumOneof::FOO_NOT_SET);
+}
+
+TEST(GENERATED_MESSAGE_TEST_NAME, ShrunkenEnumConcurrentMutations) {
+  UNITTEST::TestShrunkenEnumPacking message;
+  // Initialize has-bits before threads start so concurrent field writes do not
+  // race on has-bit bitwise |= operations.
+  message.set_e1(UNITTEST::ENUM1_U_ONE);
+  message.set_e2(UNITTEST::ENUM1_S_MIN);
+  message.set_e3(UNITTEST::ENUM2_U_ONE);
+  message.set_b1(true);
+  message.set_b2(true);
+  message.set_b3(true);
+  message.set_b4(true);
+
+  std::atomic<bool> start{false};
+  constexpr int kIterations = 10000;
+
+  auto worker = [&](auto mutator) {
+    while (!start.load(std::memory_order_acquire)) {
+    }
+    for (int i = 0; i < kIterations; ++i) {
+      mutator(i);
+    }
+  };
+
+  std::vector<std::thread> threads;
+  threads.emplace_back(worker, [&](int i) {
+    message.set_e1(i % 2 == 0 ? UNITTEST::ENUM1_U_ONE : UNITTEST::ENUM1_U_MAX);
+  });
+  threads.emplace_back(worker, [&](int i) {
+    message.set_e2(i % 2 == 0 ? UNITTEST::ENUM1_S_MIN : UNITTEST::ENUM1_S_MAX);
+  });
+  threads.emplace_back(worker, [&](int i) {
+    message.set_e3(i % 2 == 0 ? UNITTEST::ENUM2_U_ONE : UNITTEST::ENUM2_U_MAX);
+  });
+  threads.emplace_back(worker, [&](int i) { message.set_b1(i % 2 == 0); });
+  threads.emplace_back(worker, [&](int i) { message.set_b2(i % 2 == 1); });
+  threads.emplace_back(worker, [&](int i) { message.set_b3(i % 2 == 0); });
+  threads.emplace_back(worker, [&](int i) { message.set_b4(i % 2 == 1); });
+
+  start.store(true, std::memory_order_release);
+  for (auto& t : threads) {
+    t.join();
+  }
+
+  EXPECT_TRUE(message.e1() == UNITTEST::ENUM1_U_ONE ||
+              message.e1() == UNITTEST::ENUM1_U_MAX);
+  EXPECT_TRUE(message.e2() == UNITTEST::ENUM1_S_MIN ||
+              message.e2() == UNITTEST::ENUM1_S_MAX);
+  EXPECT_TRUE(message.e3() == UNITTEST::ENUM2_U_ONE ||
+              message.e3() == UNITTEST::ENUM2_U_MAX);
+}
+#endif  // !UNITTEST_PROFILE_DRIVEN
+
 // ===================================================================
 
 // This test must run last.  It verifies that descriptors were or were not
diff --git a/src/google/protobuf/compiler/csharp/c_sharp_features.pb.h b/src/google/protobuf/compiler/csharp/c_sharp_features.pb.h
index 1735d47..cba0b76 100755
--- a/src/google/protobuf/compiler/csharp/c_sharp_features.pb.h
+++ b/src/google/protobuf/compiler/csharp/c_sharp_features.pb.h
@@ -260,6 +260,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -275,6 +276,7 @@
     bool nullable_reference_types_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fcsharp_2fc_5fsharp_5ffeatures_2eproto;
 };
diff --git a/src/google/protobuf/compiler/java/java_features.pb.cc b/src/google/protobuf/compiler/java/java_features.pb.cc
index bb2dc48..301d67f 100644
--- a/src/google/protobuf/compiler/java/java_features.pb.cc
+++ b/src/google/protobuf/compiler/java/java_features.pb.cc
@@ -159,12 +159,12 @@
     }, {{
       {::_pbi::TcParser::MiniParse, {}},
       // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {::_pbi::TcParser::SingularVarintNoZag1<bool, offsetof(JavaFeatures, _impl_.legacy_closed_enum_), 1>(),
-       {8, 1, 0,
+      {::_pbi::TcParser::SingularVarintNoZag1<bool, offsetof(JavaFeatures, _impl_.legacy_closed_enum_), 0>(),
+       {8, 0, 0,
         PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.legacy_closed_enum_)}},
       // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {::_pbi::TcParser::FastEr0S1,
-       {16, 0, 2,
+      {::_pbi::TcParser::FastEr8S1,
+       {16, 1, 0,
         PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.utf8_validation_)}},
       // optional bool large_enum = 3 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = {
       {::_pbi::TcParser::SingularVarintNoZag1<bool, offsetof(JavaFeatures, _impl_.large_enum_), 2>(),
@@ -175,8 +175,8 @@
        {32, 3, 0,
         PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.use_old_outer_classname_default_)}},
       // optional .pb.JavaFeatures.NestInFileClassFeature.NestInFileClass nest_in_file_class = 5 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_SERVICE, edition_defaults = {
-      {::_pbi::TcParser::FastEr0S1,
-       {40, 4, 3,
+      {::_pbi::TcParser::FastEr8S1,
+       {40, 4, 1,
         PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.nest_in_file_class_)}},
       {::_pbi::TcParser::MiniParse, {}},
       {::_pbi::TcParser::MiniParse, {}},
@@ -184,15 +184,15 @@
       65535, 65535
     }}, {{
       // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.legacy_closed_enum_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)},
+      {PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.legacy_closed_enum_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)},
       // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.utf8_validation_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.utf8_validation_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
       // optional bool large_enum = 3 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = {
       {PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.large_enum_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)},
       // optional bool use_old_outer_classname_default = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FILE, edition_defaults = {
       {PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.use_old_outer_classname_default_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)},
       // optional .pb.JavaFeatures.NestInFileClassFeature.NestInFileClass nest_in_file_class = 5 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_SERVICE, edition_defaults = {
-      {PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.nest_in_file_class_), _Internal::kHasBitsOffset + 4, 1, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.nest_in_file_class_), _Internal::kHasBitsOffset + 4, 1, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
     }},
     {{
         {0, 2},
@@ -207,8 +207,8 @@
 inline constexpr JavaFeatures::Impl_::Impl_(
     [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility,
     ::_pbi::ConstantInitialized) noexcept
-      : utf8_validation_{static_cast< ::pb::JavaFeatures_Utf8Validation >(0)},
-        legacy_closed_enum_{false},
+      : legacy_closed_enum_{false},
+        utf8_validation_{static_cast< ::pb::JavaFeatures_Utf8Validation >(0)},
         large_enum_{false},
         use_old_outer_classname_default_{false},
         nest_in_file_class_{static_cast< ::pb::JavaFeatures_NestInFileClassFeature_NestInFileClass >(0)} {}
@@ -279,12 +279,12 @@
         PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_._has_bits_),
         8, // hasbit index offset
         PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_.legacy_closed_enum_),
-        PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_.utf8_validation_),
+        PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_.utf8_validation_) | ::_pbi::kEnum8OffsetTag,
         PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_.large_enum_),
         PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_.use_old_outer_classname_default_),
-        PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_.nest_in_file_class_),
-        1,
+        PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_.nest_in_file_class_) | ::_pbi::kEnum8OffsetTag,
         0,
+        1,
         2,
         3,
         4,
@@ -446,10 +446,10 @@
   JavaFeatures& this_ = static_cast<JavaFeatures&>(self);
   new (&this_._impl_) Impl_(this_.internal_visibility(), arena);
   ::memset(reinterpret_cast<char*>(&this_._impl_) +
-               offsetof(Impl_, utf8_validation_),
+               offsetof(Impl_, legacy_closed_enum_),
            0,
            offsetof(Impl_, nest_in_file_class_) -
-               offsetof(Impl_, utf8_validation_) +
+               offsetof(Impl_, legacy_closed_enum_) +
                sizeof(Impl_::nest_in_file_class_));
 }
 JavaFeatures::~JavaFeatures() {
@@ -487,10 +487,10 @@
 
   cached_has_bits = this_._impl_._has_bits_[0];
   if (BatchCheckHasBit(cached_has_bits, 0x0000001fU)) {
-    ::memset(&this_._impl_.utf8_validation_, 0,
+    ::memset(&this_._impl_.legacy_closed_enum_, 0,
              static_cast<::size_t>(
                  reinterpret_cast<char*>(&this_._impl_.nest_in_file_class_) -
-                 reinterpret_cast<char*>(&this_._impl_.utf8_validation_)) +
+                 reinterpret_cast<char*>(&this_._impl_.legacy_closed_enum_)) +
                  sizeof(_impl_.nest_in_file_class_));
   }
   this_._impl_._has_bits_.Clear();
@@ -517,14 +517,14 @@
 
   cached_has_bits = this_._impl_._has_bits_[0];
   // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-  if (CheckHasBit(cached_has_bits, 0x00000002U)) {
+  if (CheckHasBit(cached_has_bits, 0x00000001U)) {
     target = stream->EnsureSpace(target);
     target = ::_pbi::WireFormatLite::WriteBoolToArray(
         1, this_._internal_legacy_closed_enum(), target);
   }
 
   // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-  if (CheckHasBit(cached_has_bits, 0x00000001U)) {
+  if (CheckHasBit(cached_has_bits, 0x00000002U)) {
     target = stream->EnsureSpace(target);
     target = ::_pbi::WireFormatLite::WriteEnumToArray(
         2, this_._internal_utf8_validation(), target);
@@ -574,10 +574,10 @@
 
   ::_pbi::Prefetch5LinesFrom7Lines(&this_);
   cached_has_bits = this_._impl_._has_bits_[0];
-  total_size += ::absl::popcount(0x0000000eU & cached_has_bits) * 2;
-  if (BatchCheckHasBit(cached_has_bits, 0x00000011U)) {
+  total_size += ::absl::popcount(0x0000000dU & cached_has_bits) * 2;
+  if (BatchCheckHasBit(cached_has_bits, 0x00000012U)) {
     // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-    if (CheckHasBit(cached_has_bits, 0x00000001U)) {
+    if (CheckHasBit(cached_has_bits, 0x00000002U)) {
       total_size += 1 +
                     ::_pbi::WireFormatLite::EnumSize(this_._internal_utf8_validation());
     }
@@ -606,10 +606,10 @@
   cached_has_bits = from._impl_._has_bits_[0];
   if (BatchCheckHasBit(cached_has_bits, 0x0000001fU)) {
     if (CheckHasBit(cached_has_bits, 0x00000001U)) {
-      _this->_impl_.utf8_validation_ = from._impl_.utf8_validation_;
+      _this->_impl_.legacy_closed_enum_ = from._impl_.legacy_closed_enum_;
     }
     if (CheckHasBit(cached_has_bits, 0x00000002U)) {
-      _this->_impl_.legacy_closed_enum_ = from._impl_.legacy_closed_enum_;
+      _this->_impl_.utf8_validation_ = from._impl_.utf8_validation_;
     }
     if (CheckHasBit(cached_has_bits, 0x00000004U)) {
       _this->_impl_.large_enum_ = from._impl_.large_enum_;
@@ -643,9 +643,9 @@
   swap(this_._impl_._has_bits_[0], other->_impl_._has_bits_[0]);
   ::google::protobuf::internal::memswap<PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.nest_in_file_class_) +
                  sizeof(JavaFeatures::_impl_.nest_in_file_class_) -
-                 PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.utf8_validation_)>(
-      reinterpret_cast<char*>(&this_._impl_.utf8_validation_),
-      reinterpret_cast<char*>(&other->_impl_.utf8_validation_));
+                 PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.legacy_closed_enum_)>(
+      reinterpret_cast<char*>(&this_._impl_.legacy_closed_enum_),
+      reinterpret_cast<char*>(&other->_impl_.legacy_closed_enum_));
 }
 
 ::google::protobuf::Metadata JavaFeatures::GetMetadata() const {
diff --git a/src/google/protobuf/compiler/java/java_features.pb.h b/src/google/protobuf/compiler/java/java_features.pb.h
index dcc255f..98303d1 100644
--- a/src/google/protobuf/compiler/java/java_features.pb.h
+++ b/src/google/protobuf/compiler/java/java_features.pb.h
@@ -501,23 +501,12 @@
 
   // accessors -------------------------------------------------------
   enum : int {
-    kUtf8ValidationFieldNumber = 2,
     kLegacyClosedEnumFieldNumber = 1,
+    kUtf8ValidationFieldNumber = 2,
     kLargeEnumFieldNumber = 3,
     kUseOldOuterClassnameDefaultFieldNumber = 4,
     kNestInFileClassFieldNumber = 5,
   };
-  // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-  [[nodiscard]] bool has_utf8_validation() const;
-  void clear_utf8_validation() ;
-  [[nodiscard]] ::pb::JavaFeatures_Utf8Validation utf8_validation() const;
-  void set_utf8_validation(::pb::JavaFeatures_Utf8Validation value);
-
-  private:
-  ::pb::JavaFeatures_Utf8Validation _internal_utf8_validation() const;
-  void _internal_set_utf8_validation(::pb::JavaFeatures_Utf8Validation value);
-
-  public:
   // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
   [[nodiscard]] bool has_legacy_closed_enum() const;
   void clear_legacy_closed_enum() ;
@@ -529,6 +518,17 @@
   void _internal_set_legacy_closed_enum(bool value);
 
   public:
+  // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
+  [[nodiscard]] bool has_utf8_validation() const;
+  void clear_utf8_validation() ;
+  [[nodiscard]] ::pb::JavaFeatures_Utf8Validation utf8_validation() const;
+  void set_utf8_validation(::pb::JavaFeatures_Utf8Validation value);
+
+  private:
+  ::pb::JavaFeatures_Utf8Validation _internal_utf8_validation() const;
+  void _internal_set_utf8_validation(::pb::JavaFeatures_Utf8Validation value);
+
+  public:
   // optional bool large_enum = 3 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = {
   [[nodiscard]] bool has_large_enum() const;
   void clear_large_enum() ;
@@ -593,6 +593,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -605,13 +606,14 @@
         const JavaFeatures& from_msg);
     ::google::protobuf::internal::HasBits<1> _has_bits_;
     ::google::protobuf::internal::CachedSize _cached_size_;
-    int utf8_validation_;
     bool legacy_closed_enum_;
+    uint8_t utf8_validation_;
     bool large_enum_;
     bool use_old_outer_classname_default_;
-    int nest_in_file_class_;
+    uint8_t nest_in_file_class_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto;
 };
@@ -641,13 +643,13 @@
 
 // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
 inline bool JavaFeatures::has_legacy_closed_enum() const {
-  bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000002U);
+  bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000001U);
   return value;
 }
 inline void JavaFeatures::clear_legacy_closed_enum() {
   ::google::protobuf::internal::TSanWrite(&_impl_);
   _impl_.legacy_closed_enum_ = false;
-  ClearHasBit(_impl_._has_bits_[0], 0x00000002U);
+  ClearHasBit(_impl_._has_bits_[0], 0x00000001U);
 }
 inline bool JavaFeatures::legacy_closed_enum() const {
   // @@protoc_insertion_point(field_get:pb.JavaFeatures.legacy_closed_enum)
@@ -655,7 +657,7 @@
 }
 inline void JavaFeatures::set_legacy_closed_enum(bool value) {
   _internal_set_legacy_closed_enum(value);
-  SetHasBit(_impl_._has_bits_[0], 0x00000002U);
+  SetHasBit(_impl_._has_bits_[0], 0x00000001U);
   // @@protoc_insertion_point(field_set:pb.JavaFeatures.legacy_closed_enum)
 }
 inline bool JavaFeatures::_internal_legacy_closed_enum() const {
@@ -669,13 +671,13 @@
 
 // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
 inline bool JavaFeatures::has_utf8_validation() const {
-  bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000001U);
+  bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000002U);
   return value;
 }
 inline void JavaFeatures::clear_utf8_validation() {
   ::google::protobuf::internal::TSanWrite(&_impl_);
   _impl_.utf8_validation_ = 0;
-  ClearHasBit(_impl_._has_bits_[0], 0x00000001U);
+  ClearHasBit(_impl_._has_bits_[0], 0x00000002U);
 }
 inline ::pb::JavaFeatures_Utf8Validation JavaFeatures::utf8_validation() const {
   // @@protoc_insertion_point(field_get:pb.JavaFeatures.utf8_validation)
@@ -683,7 +685,7 @@
 }
 inline void JavaFeatures::set_utf8_validation(::pb::JavaFeatures_Utf8Validation value) {
   _internal_set_utf8_validation(value);
-  SetHasBit(_impl_._has_bits_[0], 0x00000001U);
+  SetHasBit(_impl_._has_bits_[0], 0x00000002U);
   // @@protoc_insertion_point(field_set:pb.JavaFeatures.utf8_validation)
 }
 inline ::pb::JavaFeatures_Utf8Validation JavaFeatures::_internal_utf8_validation() const {
@@ -695,7 +697,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::pb::JavaFeatures_Utf8Validation_internal_data_));
-                                          _impl_.utf8_validation_ = value;
+                                          _impl_.utf8_validation_ = static_cast<uint8_t>(value);
 }
 
 // optional bool large_enum = 3 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = {
@@ -782,7 +784,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::pb::JavaFeatures_NestInFileClassFeature_NestInFileClass_internal_data_));
-                                          _impl_.nest_in_file_class_ = value;
+                                          _impl_.nest_in_file_class_ = static_cast<uint8_t>(value);
 }
 
 #ifdef __GNUC__
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index cb51823..f09569e 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -356,6 +356,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -374,6 +375,7 @@
     ::int32_t patch_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
 };
@@ -625,6 +627,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -643,6 +646,7 @@
     ::google::protobuf::GeneratedCodeInfo* PROTOBUF_NULLABLE generated_code_info_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
 };
@@ -923,6 +927,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -942,6 +947,7 @@
     ::int32_t maximum_edition_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
 };
@@ -1233,6 +1239,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -1252,6 +1259,7 @@
     ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > source_file_descriptors_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
 };
diff --git a/src/google/protobuf/cpp_features.pb.cc b/src/google/protobuf/cpp_features.pb.cc
index 1bfe248..d2a0ea6 100644
--- a/src/google/protobuf/cpp_features.pb.cc
+++ b/src/google/protobuf/cpp_features.pb.cc
@@ -66,16 +66,16 @@
       ::_pbi::TcParser::MpUnknownFields,  // fallback
     }, {{
       // optional .pb.CppFeatures.RepeatedType repeated_type = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {::_pbi::TcParser::FastEr0S1,
-       {32, 3, 2,
+      {::_pbi::TcParser::FastEr8S1,
+       {32, 3, 1,
         PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.repeated_type_)}},
       // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {::_pbi::TcParser::SingularVarintNoZag1<bool, offsetof(CppFeatures, _impl_.legacy_closed_enum_), 1>(),
-       {8, 1, 0,
+      {::_pbi::TcParser::SingularVarintNoZag1<bool, offsetof(CppFeatures, _impl_.legacy_closed_enum_), 0>(),
+       {8, 0, 0,
         PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.legacy_closed_enum_)}},
       // optional .pb.CppFeatures.StringType string_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {::_pbi::TcParser::FastEr0S1,
-       {16, 0, 3,
+      {::_pbi::TcParser::FastEr8S1,
+       {16, 1, 0,
         PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.string_type_)}},
       // optional bool enum_name_uses_string_view = 3 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = {
       {::_pbi::TcParser::SingularVarintNoZag1<bool, offsetof(CppFeatures, _impl_.enum_name_uses_string_view_), 2>(),
@@ -85,13 +85,13 @@
       65535, 65535
     }}, {{
       // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.legacy_closed_enum_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)},
+      {PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.legacy_closed_enum_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)},
       // optional .pb.CppFeatures.StringType string_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.string_type_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.string_type_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
       // optional bool enum_name_uses_string_view = 3 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = {
       {PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.enum_name_uses_string_view_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)},
       // optional .pb.CppFeatures.RepeatedType repeated_type = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.repeated_type_), _Internal::kHasBitsOffset + 3, 1, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.repeated_type_), _Internal::kHasBitsOffset + 3, 1, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
     }},
     {{
         {0, 3},
@@ -106,8 +106,8 @@
 inline constexpr CppFeatures::Impl_::Impl_(
     [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility,
     ::_pbi::ConstantInitialized) noexcept
-      : string_type_{static_cast< ::pb::CppFeatures_StringType >(0)},
-        legacy_closed_enum_{false},
+      : legacy_closed_enum_{false},
+        string_type_{static_cast< ::pb::CppFeatures_StringType >(0)},
         enum_name_uses_string_view_{false},
         repeated_type_{static_cast< ::pb::CppFeatures_RepeatedType >(0)} {}
 
@@ -176,11 +176,11 @@
         PROTOBUF_FIELD_OFFSET(::pb::CppFeatures, _impl_._has_bits_),
         7, // hasbit index offset
         PROTOBUF_FIELD_OFFSET(::pb::CppFeatures, _impl_.legacy_closed_enum_),
-        PROTOBUF_FIELD_OFFSET(::pb::CppFeatures, _impl_.string_type_),
+        PROTOBUF_FIELD_OFFSET(::pb::CppFeatures, _impl_.string_type_) | ::_pbi::kEnum8OffsetTag,
         PROTOBUF_FIELD_OFFSET(::pb::CppFeatures, _impl_.enum_name_uses_string_view_),
-        PROTOBUF_FIELD_OFFSET(::pb::CppFeatures, _impl_.repeated_type_),
-        1,
+        PROTOBUF_FIELD_OFFSET(::pb::CppFeatures, _impl_.repeated_type_) | ::_pbi::kEnum8OffsetTag,
         0,
+        1,
         2,
         3,
 };
@@ -284,10 +284,10 @@
   CppFeatures& this_ = static_cast<CppFeatures&>(self);
   new (&this_._impl_) Impl_(this_.internal_visibility(), arena);
   ::memset(reinterpret_cast<char*>(&this_._impl_) +
-               offsetof(Impl_, string_type_),
+               offsetof(Impl_, legacy_closed_enum_),
            0,
            offsetof(Impl_, repeated_type_) -
-               offsetof(Impl_, string_type_) +
+               offsetof(Impl_, legacy_closed_enum_) +
                sizeof(Impl_::repeated_type_));
 }
 CppFeatures::~CppFeatures() {
@@ -323,14 +323,11 @@
   ::google::protobuf::internal::TSanWrite(&this_._impl_);
   ::uint32_t cached_has_bits [[maybe_unused]] = 0;
 
-  cached_has_bits = this_._impl_._has_bits_[0];
-  if (BatchCheckHasBit(cached_has_bits, 0x0000000fU)) {
-    ::memset(&this_._impl_.string_type_, 0,
-             static_cast<::size_t>(
-                 reinterpret_cast<char*>(&this_._impl_.repeated_type_) -
-                 reinterpret_cast<char*>(&this_._impl_.string_type_)) +
-                 sizeof(_impl_.repeated_type_));
-  }
+  ::memset(&this_._impl_.legacy_closed_enum_, 0,
+           static_cast<::size_t>(
+               reinterpret_cast<char*>(&this_._impl_.repeated_type_) -
+               reinterpret_cast<char*>(&this_._impl_.legacy_closed_enum_)) +
+               sizeof(_impl_.repeated_type_));
   this_._impl_._has_bits_.Clear();
   this_._internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>();
 }
@@ -355,14 +352,14 @@
 
   cached_has_bits = this_._impl_._has_bits_[0];
   // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-  if (CheckHasBit(cached_has_bits, 0x00000002U)) {
+  if (CheckHasBit(cached_has_bits, 0x00000001U)) {
     target = stream->EnsureSpace(target);
     target = ::_pbi::WireFormatLite::WriteBoolToArray(
         1, this_._internal_legacy_closed_enum(), target);
   }
 
   // optional .pb.CppFeatures.StringType string_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-  if (CheckHasBit(cached_has_bits, 0x00000001U)) {
+  if (CheckHasBit(cached_has_bits, 0x00000002U)) {
     target = stream->EnsureSpace(target);
     target = ::_pbi::WireFormatLite::WriteEnumToArray(
         2, this_._internal_string_type(), target);
@@ -405,10 +402,10 @@
 
   ::_pbi::Prefetch5LinesFrom7Lines(&this_);
   cached_has_bits = this_._impl_._has_bits_[0];
-  total_size += ::absl::popcount(0x00000006U & cached_has_bits) * 2;
-  if (BatchCheckHasBit(cached_has_bits, 0x00000009U)) {
+  total_size += ::absl::popcount(0x00000005U & cached_has_bits) * 2;
+  if (BatchCheckHasBit(cached_has_bits, 0x0000000aU)) {
     // optional .pb.CppFeatures.StringType string_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-    if (CheckHasBit(cached_has_bits, 0x00000001U)) {
+    if (CheckHasBit(cached_has_bits, 0x00000002U)) {
       total_size += 1 +
                     ::_pbi::WireFormatLite::EnumSize(this_._internal_string_type());
     }
@@ -437,10 +434,10 @@
   cached_has_bits = from._impl_._has_bits_[0];
   if (BatchCheckHasBit(cached_has_bits, 0x0000000fU)) {
     if (CheckHasBit(cached_has_bits, 0x00000001U)) {
-      _this->_impl_.string_type_ = from._impl_.string_type_;
+      _this->_impl_.legacy_closed_enum_ = from._impl_.legacy_closed_enum_;
     }
     if (CheckHasBit(cached_has_bits, 0x00000002U)) {
-      _this->_impl_.legacy_closed_enum_ = from._impl_.legacy_closed_enum_;
+      _this->_impl_.string_type_ = from._impl_.string_type_;
     }
     if (CheckHasBit(cached_has_bits, 0x00000004U)) {
       _this->_impl_.enum_name_uses_string_view_ = from._impl_.enum_name_uses_string_view_;
@@ -471,9 +468,9 @@
   swap(this_._impl_._has_bits_[0], other->_impl_._has_bits_[0]);
   ::google::protobuf::internal::memswap<PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.repeated_type_) +
                  sizeof(CppFeatures::_impl_.repeated_type_) -
-                 PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.string_type_)>(
-      reinterpret_cast<char*>(&this_._impl_.string_type_),
-      reinterpret_cast<char*>(&other->_impl_.string_type_));
+                 PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.legacy_closed_enum_)>(
+      reinterpret_cast<char*>(&this_._impl_.legacy_closed_enum_),
+      reinterpret_cast<char*>(&other->_impl_.legacy_closed_enum_));
 }
 
 ::google::protobuf::Metadata CppFeatures::GetMetadata() const {
diff --git a/src/google/protobuf/cpp_features.pb.h b/src/google/protobuf/cpp_features.pb.h
index 683e1d3..32293e8 100644
--- a/src/google/protobuf/cpp_features.pb.h
+++ b/src/google/protobuf/cpp_features.pb.h
@@ -347,22 +347,11 @@
 
   // accessors -------------------------------------------------------
   enum : int {
-    kStringTypeFieldNumber = 2,
     kLegacyClosedEnumFieldNumber = 1,
+    kStringTypeFieldNumber = 2,
     kEnumNameUsesStringViewFieldNumber = 3,
     kRepeatedTypeFieldNumber = 4,
   };
-  // optional .pb.CppFeatures.StringType string_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-  [[nodiscard]] bool has_string_type() const;
-  void clear_string_type() ;
-  [[nodiscard]] ::pb::CppFeatures_StringType string_type() const;
-  void set_string_type(::pb::CppFeatures_StringType value);
-
-  private:
-  ::pb::CppFeatures_StringType _internal_string_type() const;
-  void _internal_set_string_type(::pb::CppFeatures_StringType value);
-
-  public:
   // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
   [[nodiscard]] bool has_legacy_closed_enum() const;
   void clear_legacy_closed_enum() ;
@@ -374,6 +363,17 @@
   void _internal_set_legacy_closed_enum(bool value);
 
   public:
+  // optional .pb.CppFeatures.StringType string_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
+  [[nodiscard]] bool has_string_type() const;
+  void clear_string_type() ;
+  [[nodiscard]] ::pb::CppFeatures_StringType string_type() const;
+  void set_string_type(::pb::CppFeatures_StringType value);
+
+  private:
+  ::pb::CppFeatures_StringType _internal_string_type() const;
+  void _internal_set_string_type(::pb::CppFeatures_StringType value);
+
+  public:
   // optional bool enum_name_uses_string_view = 3 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = {
   [[nodiscard]] bool has_enum_name_uses_string_view() const;
   void clear_enum_name_uses_string_view() ;
@@ -427,6 +427,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -439,12 +440,13 @@
         const CppFeatures& from_msg);
     ::google::protobuf::internal::HasBits<1> _has_bits_;
     ::google::protobuf::internal::CachedSize _cached_size_;
-    int string_type_;
     bool legacy_closed_enum_;
+    uint8_t string_type_;
     bool enum_name_uses_string_view_;
-    int repeated_type_;
+    uint8_t repeated_type_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fcpp_5ffeatures_2eproto;
 };
@@ -470,13 +472,13 @@
 
 // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
 inline bool CppFeatures::has_legacy_closed_enum() const {
-  bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000002U);
+  bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000001U);
   return value;
 }
 inline void CppFeatures::clear_legacy_closed_enum() {
   ::google::protobuf::internal::TSanWrite(&_impl_);
   _impl_.legacy_closed_enum_ = false;
-  ClearHasBit(_impl_._has_bits_[0], 0x00000002U);
+  ClearHasBit(_impl_._has_bits_[0], 0x00000001U);
 }
 inline bool CppFeatures::legacy_closed_enum() const {
   // @@protoc_insertion_point(field_get:pb.CppFeatures.legacy_closed_enum)
@@ -484,7 +486,7 @@
 }
 inline void CppFeatures::set_legacy_closed_enum(bool value) {
   _internal_set_legacy_closed_enum(value);
-  SetHasBit(_impl_._has_bits_[0], 0x00000002U);
+  SetHasBit(_impl_._has_bits_[0], 0x00000001U);
   // @@protoc_insertion_point(field_set:pb.CppFeatures.legacy_closed_enum)
 }
 inline bool CppFeatures::_internal_legacy_closed_enum() const {
@@ -498,13 +500,13 @@
 
 // optional .pb.CppFeatures.StringType string_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
 inline bool CppFeatures::has_string_type() const {
-  bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000001U);
+  bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000002U);
   return value;
 }
 inline void CppFeatures::clear_string_type() {
   ::google::protobuf::internal::TSanWrite(&_impl_);
   _impl_.string_type_ = 0;
-  ClearHasBit(_impl_._has_bits_[0], 0x00000001U);
+  ClearHasBit(_impl_._has_bits_[0], 0x00000002U);
 }
 inline ::pb::CppFeatures_StringType CppFeatures::string_type() const {
   // @@protoc_insertion_point(field_get:pb.CppFeatures.string_type)
@@ -512,7 +514,7 @@
 }
 inline void CppFeatures::set_string_type(::pb::CppFeatures_StringType value) {
   _internal_set_string_type(value);
-  SetHasBit(_impl_._has_bits_[0], 0x00000001U);
+  SetHasBit(_impl_._has_bits_[0], 0x00000002U);
   // @@protoc_insertion_point(field_set:pb.CppFeatures.string_type)
 }
 inline ::pb::CppFeatures_StringType CppFeatures::_internal_string_type() const {
@@ -524,7 +526,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::pb::CppFeatures_StringType_internal_data_));
-                                          _impl_.string_type_ = value;
+                                          _impl_.string_type_ = static_cast<uint8_t>(value);
 }
 
 // optional bool enum_name_uses_string_view = 3 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = {
@@ -583,7 +585,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::pb::CppFeatures_RepeatedType_internal_data_));
-                                          _impl_.repeated_type_ = value;
+                                          _impl_.repeated_type_ = static_cast<uint8_t>(value);
 }
 
 #ifdef __GNUC__
diff --git a/src/google/protobuf/cpp_file_options.pb.h b/src/google/protobuf/cpp_file_options.pb.h
index b7ae9c4..a84d436 100644
--- a/src/google/protobuf/cpp_file_options.pb.h
+++ b/src/google/protobuf/cpp_file_options.pb.h
@@ -257,6 +257,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -272,6 +273,7 @@
     ::google::protobuf::internal::ArenaStringPtr namespace__;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fcpp_5ffile_5foptions_2eproto;
 };
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index 7f5a4c1..75d7711 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -437,8 +437,8 @@
        {32, 3, 0,
         PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _impl_.end_)}},
       // optional .google.protobuf.GeneratedCodeInfo.Annotation.Semantic semantic = 5;
-      {::_pbi::TcParser::FastEr0S1,
-       {40, 4, 2,
+      {::_pbi::TcParser::FastEr8S1,
+       {40, 4, 0,
         PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _impl_.semantic_)}},
       {::_pbi::TcParser::MiniParse, {}},
       {::_pbi::TcParser::MiniParse, {}},
@@ -454,7 +454,7 @@
       // optional int32 end = 4;
       {PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _impl_.end_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kInt32)},
       // optional .google.protobuf.GeneratedCodeInfo.Annotation.Semantic semantic = 5;
-      {PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _impl_.semantic_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _impl_.semantic_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
     }},
     {{
         {0, 2},
@@ -1041,40 +1041,40 @@
     }, {{
       {::_pbi::TcParser::MiniParse, {}},
       // optional .google.protobuf.FeatureSet.FieldPresence field_presence = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {::_pbi::TcParser::FastEr0S1,
-       {8, 0, 3,
+      {::_pbi::TcParser::FastEr8S1,
+       {8, 0, 0,
         PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.field_presence_)}},
       // optional .google.protobuf.FeatureSet.EnumType enum_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {::_pbi::TcParser::FastEr0S1,
-       {16, 1, 2,
+      {::_pbi::TcParser::FastEr8S1,
+       {16, 1, 1,
         PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.enum_type_)}},
       // optional .google.protobuf.FeatureSet.RepeatedFieldEncoding repeated_field_encoding = 3 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {::_pbi::TcParser::FastEr0S1,
+      {::_pbi::TcParser::FastEr8S1,
        {24, 2, 2,
         PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.repeated_field_encoding_)}},
       // optional .google.protobuf.FeatureSet.Utf8Validation utf8_validation = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {::_pbi::TcParser::FastEvS1,
+      {::_pbi::TcParser::FastEv8S1,
        {32, 3, 3,
         PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.utf8_validation_)}},
       // optional .google.protobuf.FeatureSet.MessageEncoding message_encoding = 5 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {::_pbi::TcParser::FastEr0S1,
-       {40, 4, 2,
+      {::_pbi::TcParser::FastEr8S1,
+       {40, 4, 4,
         PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.message_encoding_)}},
       // optional .google.protobuf.FeatureSet.JsonFormat json_format = 6 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {::_pbi::TcParser::FastEr0S1,
-       {48, 5, 2,
+      {::_pbi::TcParser::FastEr8S1,
+       {48, 5, 5,
         PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.json_format_)}},
       // optional .google.protobuf.FeatureSet.EnforceNamingStyle enforce_naming_style = 7 [retention = RETENTION_SOURCE, targets = TARGET_TYPE_FILE, targets = TARGET_TYPE_EXTENSION_RANGE, targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_ONEOF, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_ENUM_ENTRY, targets = TARGET_TYPE_SERVICE, targets = TARGET_TYPE_METHOD, edition_defaults = {
-      {::_pbi::TcParser::FastEr0S1,
-       {56, 6, 3,
+      {::_pbi::TcParser::FastEr8S1,
+       {56, 6, 6,
         PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.enforce_naming_style_)}},
       // optional .google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility default_symbol_visibility = 8 [retention = RETENTION_SOURCE, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {::_pbi::TcParser::FastEr0S1,
-       {64, 7, 4,
+      {::_pbi::TcParser::FastEr8S1,
+       {64, 7, 7,
         PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.default_symbol_visibility_)}},
       // optional .google.protobuf.FeatureSet.ProtoLimitsFeature.EnforceProtoLimits enforce_proto_limits = 9 [retention = RETENTION_SOURCE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_ONEOF, edition_defaults = {
-      {::_pbi::TcParser::FastEr0S1,
-       {72, 8, 2,
+      {::_pbi::TcParser::FastEr8S1,
+       {72, 8, 8,
         PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.enforce_proto_limits_)}},
       {::_pbi::TcParser::MiniParse, {}},
       {::_pbi::TcParser::MiniParse, {}},
@@ -1086,23 +1086,23 @@
       65535, 65535
     }}, {{
       // optional .google.protobuf.FeatureSet.FieldPresence field_presence = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.field_presence_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.field_presence_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
       // optional .google.protobuf.FeatureSet.EnumType enum_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.enum_type_), _Internal::kHasBitsOffset + 1, 1, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.enum_type_), _Internal::kHasBitsOffset + 1, 1, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
       // optional .google.protobuf.FeatureSet.RepeatedFieldEncoding repeated_field_encoding = 3 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.repeated_field_encoding_), _Internal::kHasBitsOffset + 2, 2, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.repeated_field_encoding_), _Internal::kHasBitsOffset + 2, 2, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
       // optional .google.protobuf.FeatureSet.Utf8Validation utf8_validation = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.utf8_validation_), _Internal::kHasBitsOffset + 3, 3, (0 | ::_fl::kFcOptional | ::_fl::kEnum)},
+      {PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.utf8_validation_), _Internal::kHasBitsOffset + 3, 3, (0 | ::_fl::kFcOptional | ::_fl::kEnum8)},
       // optional .google.protobuf.FeatureSet.MessageEncoding message_encoding = 5 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.message_encoding_), _Internal::kHasBitsOffset + 4, 4, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.message_encoding_), _Internal::kHasBitsOffset + 4, 4, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
       // optional .google.protobuf.FeatureSet.JsonFormat json_format = 6 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.json_format_), _Internal::kHasBitsOffset + 5, 5, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.json_format_), _Internal::kHasBitsOffset + 5, 5, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
       // optional .google.protobuf.FeatureSet.EnforceNamingStyle enforce_naming_style = 7 [retention = RETENTION_SOURCE, targets = TARGET_TYPE_FILE, targets = TARGET_TYPE_EXTENSION_RANGE, targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_ONEOF, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_ENUM_ENTRY, targets = TARGET_TYPE_SERVICE, targets = TARGET_TYPE_METHOD, edition_defaults = {
-      {PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.enforce_naming_style_), _Internal::kHasBitsOffset + 6, 6, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.enforce_naming_style_), _Internal::kHasBitsOffset + 6, 6, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
       // optional .google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility default_symbol_visibility = 8 [retention = RETENTION_SOURCE, targets = TARGET_TYPE_FILE, edition_defaults = {
-      {PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.default_symbol_visibility_), _Internal::kHasBitsOffset + 7, 7, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.default_symbol_visibility_), _Internal::kHasBitsOffset + 7, 7, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
       // optional .google.protobuf.FeatureSet.ProtoLimitsFeature.EnforceProtoLimits enforce_proto_limits = 9 [retention = RETENTION_SOURCE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_ONEOF, edition_defaults = {
-      {PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.enforce_proto_limits_), _Internal::kHasBitsOffset + 8, 8, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_.enforce_proto_limits_), _Internal::kHasBitsOffset + 8, 8, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
     }},
     {{
         {0, 3},
@@ -2427,7 +2427,7 @@
        {648, 2, 0,
         PROTOBUF_FIELD_OFFSET(MethodOptions, _impl_.deprecated_)}},
       // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN];
-      {::_pbi::TcParser::FastEr0S2,
+      {::_pbi::TcParser::FastEr8S2,
        {656, 3, 2,
         PROTOBUF_FIELD_OFFSET(MethodOptions, _impl_.idempotency_level_)}},
       // optional .google.protobuf.FeatureSet features = 35;
@@ -2451,7 +2451,7 @@
       // optional bool deprecated = 33 [default = false];
       {PROTOBUF_FIELD_OFFSET(MethodOptions, _impl_.deprecated_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)},
       // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN];
-      {PROTOBUF_FIELD_OFFSET(MethodOptions, _impl_.idempotency_level_), _Internal::kHasBitsOffset + 3, 2, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(MethodOptions, _impl_.idempotency_level_), _Internal::kHasBitsOffset + 3, 2, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
       // optional .google.protobuf.FeatureSet features = 35;
       {PROTOBUF_FIELD_OFFSET(MethodOptions, _impl_.features_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvClassData)},
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
@@ -2746,8 +2746,8 @@
        {66, 1, 0,
         PROTOBUF_FIELD_OFFSET(FileOptions, _impl_.java_outer_classname_)}},
       // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
-      {::_pbi::TcParser::FastEr1S1,
-       {72, 18, 3,
+      {::_pbi::TcParser::FastEr8S1,
+       {72, 18, 2,
         PROTOBUF_FIELD_OFFSET(FileOptions, _impl_.optimize_for_)}},
       // optional bool java_multiple_files = 10 [default = false, feature_support = {
       {::_pbi::TcParser::SingularVarintNoZag1<bool, offsetof(FileOptions, _impl_.java_multiple_files_), 11>(),
@@ -2825,7 +2825,7 @@
       // optional string java_outer_classname = 8;
       {PROTOBUF_FIELD_OFFSET(FileOptions, _impl_.java_outer_classname_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kBytes | ::_fl::kRepAString)},
       // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
-      {PROTOBUF_FIELD_OFFSET(FileOptions, _impl_.optimize_for_), _Internal::kHasBitsOffset + 18, 2, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(FileOptions, _impl_.optimize_for_), _Internal::kHasBitsOffset + 18, 2, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
       // optional bool java_multiple_files = 10 [default = false, feature_support = {
       {PROTOBUF_FIELD_OFFSET(FileOptions, _impl_.java_multiple_files_), _Internal::kHasBitsOffset + 11, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)},
       // optional string go_package = 11;
@@ -3019,8 +3019,8 @@
        {384, 11, 0,
         PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.debug_redact_)}},
       // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
-      {::_pbi::TcParser::FastEr0S1,
-       {8, 4, 2,
+      {::_pbi::TcParser::FastEr8S1,
+       {8, 4, 4,
         PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.ctype_)}},
       // optional bool packed = 2;
       {::_pbi::TcParser::SingularVarintNoZag1<bool, offsetof(FieldOptions, _impl_.packed_), 5>(),
@@ -3039,8 +3039,8 @@
        {40, 7, 0,
         PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.lazy_)}},
       // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
-      {::_pbi::TcParser::FastEr0S1,
-       {48, 9, 2,
+      {::_pbi::TcParser::FastEr8S1,
+       {48, 8, 5,
         PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.jstype_)}},
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       {::_pbi::TcParser::FastMcR2,
@@ -3049,8 +3049,8 @@
       {::_pbi::TcParser::MiniParse, {}},
       {::_pbi::TcParser::MiniParse, {}},
       // optional bool weak = 10 [default = false, deprecated = true];
-      {::_pbi::TcParser::SingularVarintNoZag1<bool, offsetof(FieldOptions, _impl_.weak_), 8>(),
-       {80, 8, 0,
+      {::_pbi::TcParser::SingularVarintNoZag1<bool, offsetof(FieldOptions, _impl_.weak_), 9>(),
+       {80, 9, 0,
         PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.weak_)}},
       {::_pbi::TcParser::MiniParse, {}},
       {::_pbi::TcParser::MiniParse, {}},
@@ -3066,7 +3066,7 @@
       65535, 65535
     }}, {{
       // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
-      {PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.ctype_), _Internal::kHasBitsOffset + 4, 4, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.ctype_), _Internal::kHasBitsOffset + 4, 4, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
       // optional bool packed = 2;
       {PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.packed_), _Internal::kHasBitsOffset + 5, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)},
       // optional bool deprecated = 3 [default = false];
@@ -3074,15 +3074,15 @@
       // optional bool lazy = 5 [default = false];
       {PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.lazy_), _Internal::kHasBitsOffset + 7, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)},
       // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
-      {PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.jstype_), _Internal::kHasBitsOffset + 9, 5, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.jstype_), _Internal::kHasBitsOffset + 8, 5, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
       // optional bool weak = 10 [default = false, deprecated = true];
-      {PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.weak_), _Internal::kHasBitsOffset + 8, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)},
+      {PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.weak_), _Internal::kHasBitsOffset + 9, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)},
       // optional bool unverified_lazy = 15 [default = false];
       {PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.unverified_lazy_), _Internal::kHasBitsOffset + 10, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)},
       // optional bool debug_redact = 16 [default = false];
       {PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.debug_redact_), _Internal::kHasBitsOffset + 11, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)},
       // optional .google.protobuf.FieldOptions.OptionRetention retention = 17;
-      {PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.retention_), _Internal::kHasBitsOffset + 12, 6, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.retention_), _Internal::kHasBitsOffset + 12, 6, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
       // repeated .google.protobuf.FieldOptions.OptionTargetType targets = 19;
       {PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.targets_), _Internal::kHasBitsOffset + 13, 7, (0 | ::_fl::kFcRepeated | ::_fl::kEnumRange)},
       // repeated .google.protobuf.FieldOptions.EditionDefault edition_defaults = 20;
@@ -3129,8 +3129,8 @@
         packed_{false},
         deprecated_{false},
         lazy_{false},
-        weak_{false},
         jstype_{static_cast< ::google::protobuf::FieldOptions_JSType >(0)},
+        weak_{false},
         unverified_lazy_{false},
         debug_redact_{false},
         retention_{static_cast< ::google::protobuf::FieldOptions_OptionRetention >(0)},
@@ -3369,8 +3369,8 @@
        {18, 0, 0,
         PROTOBUF_FIELD_OFFSET(ExtensionRangeOptions, _impl_.declaration_)}},
       // optional .google.protobuf.ExtensionRangeOptions.VerificationState verification = 3 [default = UNVERIFIED, retention = RETENTION_SOURCE];
-      {::_pbi::TcParser::FastEr0S1,
-       {24, 3, 1,
+      {::_pbi::TcParser::FastEr8S1,
+       {24, 3, 3,
         PROTOBUF_FIELD_OFFSET(ExtensionRangeOptions, _impl_.verification_)}},
       {::_pbi::TcParser::MiniParse, {}},
       {::_pbi::TcParser::MiniParse, {}},
@@ -3389,7 +3389,7 @@
       // repeated .google.protobuf.ExtensionRangeOptions.Declaration declaration = 2 [retention = RETENTION_SOURCE];
       {PROTOBUF_FIELD_OFFSET(ExtensionRangeOptions, _impl_.declaration_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvClassData)},
       // optional .google.protobuf.ExtensionRangeOptions.VerificationState verification = 3 [default = UNVERIFIED, retention = RETENTION_SOURCE];
-      {PROTOBUF_FIELD_OFFSET(ExtensionRangeOptions, _impl_.verification_), _Internal::kHasBitsOffset + 3, 3, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(ExtensionRangeOptions, _impl_.verification_), _Internal::kHasBitsOffset + 3, 3, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
       // optional .google.protobuf.FeatureSet features = 50;
       {PROTOBUF_FIELD_OFFSET(ExtensionRangeOptions, _impl_.features_), _Internal::kHasBitsOffset + 2, 1, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvClassData)},
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
@@ -4114,12 +4114,12 @@
        {24, 6, 0,
         PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, _impl_.number_)}},
       // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
-      {::_pbi::TcParser::FastEr1S1,
-       {32, 9, 3,
+      {::_pbi::TcParser::FastEr8S1,
+       {32, 9, 1,
         PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, _impl_.label_)}},
       // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
-      {::_pbi::TcParser::FastEr1S1,
-       {40, 10, 18,
+      {::_pbi::TcParser::FastEr8S1,
+       {40, 10, 2,
         PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, _impl_.type_)}},
       // optional string type_name = 6;
       {::_pbi::TcParser::FastBS1,
@@ -4156,9 +4156,9 @@
       // optional int32 number = 3;
       {PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, _impl_.number_), _Internal::kHasBitsOffset + 6, 0, (0 | ::_fl::kFcOptional | ::_fl::kInt32)},
       // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
-      {PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, _impl_.label_), _Internal::kHasBitsOffset + 9, 1, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, _impl_.label_), _Internal::kHasBitsOffset + 9, 1, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
       // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
-      {PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, _impl_.type_), _Internal::kHasBitsOffset + 10, 2, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, _impl_.type_), _Internal::kHasBitsOffset + 10, 2, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
       // optional string type_name = 6;
       {PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, _impl_.type_name_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kBytes | ::_fl::kRepAString)},
       // optional string default_value = 7;
@@ -4720,8 +4720,8 @@
        {42, 2, 0,
         PROTOBUF_FIELD_OFFSET(EnumDescriptorProto, _impl_.reserved_name_)}},
       // optional .google.protobuf.SymbolVisibility visibility = 6;
-      {::_pbi::TcParser::FastEr0S1,
-       {48, 5, 2,
+      {::_pbi::TcParser::FastEr8S1,
+       {48, 5, 3,
         PROTOBUF_FIELD_OFFSET(EnumDescriptorProto, _impl_.visibility_)}},
       {::_pbi::TcParser::MiniParse, {}},
     }}, {{
@@ -4738,7 +4738,7 @@
       // repeated string reserved_name = 5;
       {PROTOBUF_FIELD_OFFSET(EnumDescriptorProto, _impl_.reserved_name_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcRepeated | ::_fl::kBytes | ::_fl::kRepSString)},
       // optional .google.protobuf.SymbolVisibility visibility = 6;
-      {PROTOBUF_FIELD_OFFSET(EnumDescriptorProto, _impl_.visibility_), _Internal::kHasBitsOffset + 5, 3, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(EnumDescriptorProto, _impl_.visibility_), _Internal::kHasBitsOffset + 5, 3, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
     }},
     {{
         {::_pbi::FieldAuxClassData(), &::google::protobuf::EnumValueDescriptorProto_globals_},
@@ -4909,8 +4909,8 @@
        {82, 7, 0,
         PROTOBUF_FIELD_OFFSET(DescriptorProto, _impl_.reserved_name_)}},
       // optional .google.protobuf.SymbolVisibility visibility = 11;
-      {::_pbi::TcParser::FastEr0S1,
-       {88, 10, 2,
+      {::_pbi::TcParser::FastEr8S1,
+       {88, 10, 8,
         PROTOBUF_FIELD_OFFSET(DescriptorProto, _impl_.visibility_)}},
       {::_pbi::TcParser::MiniParse, {}},
       {::_pbi::TcParser::MiniParse, {}},
@@ -4940,7 +4940,7 @@
       // repeated string reserved_name = 10;
       {PROTOBUF_FIELD_OFFSET(DescriptorProto, _impl_.reserved_name_), _Internal::kHasBitsOffset + 7, 0, (0 | ::_fl::kFcRepeated | ::_fl::kBytes | ::_fl::kRepSString)},
       // optional .google.protobuf.SymbolVisibility visibility = 11;
-      {PROTOBUF_FIELD_OFFSET(DescriptorProto, _impl_.visibility_), _Internal::kHasBitsOffset + 10, 8, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)},
+      {PROTOBUF_FIELD_OFFSET(DescriptorProto, _impl_.visibility_), _Internal::kHasBitsOffset + 10, 8, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange8)},
     }},
     {{
         {::_pbi::FieldAuxClassData(), &::google::protobuf::FieldDescriptorProto_globals_},
@@ -5513,7 +5513,7 @@
         PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.options_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.reserved_range_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.reserved_name_),
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.visibility_),
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.visibility_) | ::_pbi::kEnum8OffsetTag,
         8,
         0,
         4,
@@ -5545,7 +5545,7 @@
         PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions, _impl_.uninterpreted_option_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions, _impl_.declaration_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions, _impl_.features_),
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions, _impl_.verification_),
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions, _impl_.verification_) | ::_pbi::kEnum8OffsetTag,
         1,
         0,
         2,
@@ -5555,8 +5555,8 @@
         14, // hasbit index offset
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.name_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.number_),
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.label_),
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.type_),
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.label_) | ::_pbi::kEnum8OffsetTag,
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.type_) | ::_pbi::kEnum8OffsetTag,
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.type_name_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.extendee_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.default_value_),
@@ -5597,7 +5597,7 @@
         PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto, _impl_.options_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto, _impl_.reserved_range_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto, _impl_.reserved_name_),
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto, _impl_.visibility_),
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto, _impl_.visibility_) | ::_pbi::kEnum8OffsetTag,
         3,
         0,
         4,
@@ -5646,7 +5646,7 @@
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.java_multiple_files_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.java_generate_equals_and_hash_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.java_string_check_utf8_),
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.optimize_for_),
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.optimize_for_) | ::_pbi::kEnum8OffsetTag,
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.go_package_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.cc_generic_services_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.java_generic_services_),
@@ -5725,15 +5725,15 @@
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_._has_bits_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_._extensions_),
         18, // hasbit index offset
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.ctype_),
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.ctype_) | ::_pbi::kEnum8OffsetTag,
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.packed_),
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.jstype_),
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.jstype_) | ::_pbi::kEnum8OffsetTag,
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.lazy_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.unverified_lazy_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.deprecated_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.weak_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.debug_redact_),
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.retention_),
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.retention_) | ::_pbi::kEnum8OffsetTag,
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.targets_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.edition_defaults_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.features_),
@@ -5741,11 +5741,11 @@
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.uninterpreted_option_),
         4,
         5,
-        9,
+        8,
         7,
         10,
         6,
-        8,
+        9,
         11,
         12,
         13,
@@ -5804,7 +5804,7 @@
         PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _impl_._extensions_),
         8, // hasbit index offset
         PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _impl_.deprecated_),
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _impl_.idempotency_level_),
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _impl_.idempotency_level_) | ::_pbi::kEnum8OffsetTag,
         PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _impl_.features_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _impl_.uninterpreted_option_),
         2,
@@ -5841,15 +5841,15 @@
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_._has_bits_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_._extensions_),
         13, // hasbit index offset
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.field_presence_),
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.enum_type_),
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.repeated_field_encoding_),
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.utf8_validation_),
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.message_encoding_),
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.json_format_),
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.enforce_naming_style_),
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.default_symbol_visibility_),
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.enforce_proto_limits_),
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.field_presence_) | ::_pbi::kEnum8OffsetTag,
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.enum_type_) | ::_pbi::kEnum8OffsetTag,
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.repeated_field_encoding_) | ::_pbi::kEnum8OffsetTag,
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.utf8_validation_) | ::_pbi::kEnum8OffsetTag,
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.message_encoding_) | ::_pbi::kEnum8OffsetTag,
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.json_format_) | ::_pbi::kEnum8OffsetTag,
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.enforce_naming_style_) | ::_pbi::kEnum8OffsetTag,
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.default_symbol_visibility_) | ::_pbi::kEnum8OffsetTag,
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.enforce_proto_limits_) | ::_pbi::kEnum8OffsetTag,
         0,
         1,
         2,
@@ -5903,7 +5903,7 @@
         PROTOBUF_FIELD_OFFSET(::google::protobuf::GeneratedCodeInfo_Annotation, _impl_.source_file_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::GeneratedCodeInfo_Annotation, _impl_.begin_),
         PROTOBUF_FIELD_OFFSET(::google::protobuf::GeneratedCodeInfo_Annotation, _impl_.end_),
-        PROTOBUF_FIELD_OFFSET(::google::protobuf::GeneratedCodeInfo_Annotation, _impl_.semantic_),
+        PROTOBUF_FIELD_OFFSET(::google::protobuf::GeneratedCodeInfo_Annotation, _impl_.semantic_) | ::_pbi::kEnum8OffsetTag,
         0,
         1,
         2,
@@ -12831,10 +12831,10 @@
                  sizeof(_impl_.lazy_));
   }
   if (BatchCheckHasBit(cached_has_bits, 0x00003f00U)) {
-    ::memset(&this_._impl_.weak_, 0,
+    ::memset(&this_._impl_.jstype_, 0,
              static_cast<::size_t>(
                  reinterpret_cast<char*>(&this_._impl_.retention_) -
-                 reinterpret_cast<char*>(&this_._impl_.weak_)) +
+                 reinterpret_cast<char*>(&this_._impl_.jstype_)) +
                  sizeof(_impl_.retention_));
     if (CheckHasBit(cached_has_bits, 0x00002000U)) {
       this_._impl_.targets_.Clear();
@@ -12892,14 +12892,14 @@
   }
 
   // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
-  if (CheckHasBit(cached_has_bits, 0x00000200U)) {
+  if (CheckHasBit(cached_has_bits, 0x00000100U)) {
     target = stream->EnsureSpace(target);
     target = ::_pbi::WireFormatLite::WriteEnumToArray(
         6, this_._internal_jstype(), target);
   }
 
   // optional bool weak = 10 [default = false, deprecated = true];
-  if (CheckHasBit(cached_has_bits, 0x00000100U)) {
+  if (CheckHasBit(cached_has_bits, 0x00000200U)) {
     target = stream->EnsureSpace(target);
     target = ::_pbi::WireFormatLite::WriteBoolToArray(
         10, this_._internal_weak(), target);
@@ -13005,7 +13005,7 @@
   ::_pbi::Prefetch5LinesFrom7Lines(&this_);
   cached_has_bits = this_._impl_._has_bits_[0];
   total_size += static_cast<bool>(0x00000800U & cached_has_bits) * 3;
-  total_size += ::absl::popcount(0x000005e0U & cached_has_bits) * 2;
+  total_size += ::absl::popcount(0x000006e0U & cached_has_bits) * 2;
   if (BatchCheckHasBit(cached_has_bits, 0x0000001fU)) {
     // repeated .google.protobuf.FieldOptions.EditionDefault edition_defaults = 20;
     if (CheckHasBit(cached_has_bits, 0x00000001U)) {
@@ -13037,9 +13037,9 @@
                     ::_pbi::WireFormatLite::EnumSize(this_._internal_ctype());
     }
   }
-  if (BatchCheckHasBit(cached_has_bits, 0x00003200U)) {
+  if (BatchCheckHasBit(cached_has_bits, 0x00003100U)) {
     // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
-    if (CheckHasBit(cached_has_bits, 0x00000200U)) {
+    if (CheckHasBit(cached_has_bits, 0x00000100U)) {
       total_size += 1 +
                     ::_pbi::WireFormatLite::EnumSize(this_._internal_jstype());
     }
@@ -13117,10 +13117,10 @@
   }
   if (BatchCheckHasBit(cached_has_bits, 0x00003f00U)) {
     if (CheckHasBit(cached_has_bits, 0x00000100U)) {
-      _this->_impl_.weak_ = from._impl_.weak_;
+      _this->_impl_.jstype_ = from._impl_.jstype_;
     }
     if (CheckHasBit(cached_has_bits, 0x00000200U)) {
-      _this->_impl_.jstype_ = from._impl_.jstype_;
+      _this->_impl_.weak_ = from._impl_.weak_;
     }
     if (CheckHasBit(cached_has_bits, 0x00000400U)) {
       _this->_impl_.unverified_lazy_ = from._impl_.unverified_lazy_;
@@ -14546,13 +14546,11 @@
       this_._impl_.features_->Clear();
     }
   }
-  if (BatchCheckHasBit(cached_has_bits, 0x0000000cU)) {
-    ::memset(&this_._impl_.deprecated_, 0,
-             static_cast<::size_t>(
-                 reinterpret_cast<char*>(&this_._impl_.idempotency_level_) -
-                 reinterpret_cast<char*>(&this_._impl_.deprecated_)) +
-                 sizeof(_impl_.idempotency_level_));
-  }
+  ::memset(&this_._impl_.deprecated_, 0,
+           static_cast<::size_t>(
+               reinterpret_cast<char*>(&this_._impl_.idempotency_level_) -
+               reinterpret_cast<char*>(&this_._impl_.deprecated_)) +
+               sizeof(_impl_.idempotency_level_));
   this_._impl_._has_bits_.Clear();
   this_._internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>();
 }
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index b0a1b19..a4e709e 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -1296,6 +1296,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -1312,6 +1313,7 @@
     bool is_extension_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -1597,6 +1599,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -1618,6 +1621,7 @@
     ::google::protobuf::internal::CachedSize _span_cached_byte_size_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -1896,6 +1900,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -1912,10 +1917,11 @@
     ::google::protobuf::internal::ArenaStringPtr source_file_;
     ::int32_t begin_;
     ::int32_t end_;
-    int semantic_;
+    uint8_t semantic_;
     ::google::protobuf::internal::CachedSize _path_cached_byte_size_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -2170,6 +2176,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -2189,6 +2196,7 @@
     int edition_removed_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -2402,6 +2410,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -2418,6 +2427,7 @@
     int edition_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -3398,6 +3408,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -3411,17 +3422,18 @@
     ::google::protobuf::internal::ExtensionSet _extensions_;
     ::google::protobuf::internal::HasBits<1> _has_bits_;
     ::google::protobuf::internal::CachedSize _cached_size_;
-    int field_presence_;
-    int enum_type_;
-    int repeated_field_encoding_;
-    int utf8_validation_;
-    int message_encoding_;
-    int json_format_;
-    int enforce_naming_style_;
-    int default_symbol_visibility_;
-    int enforce_proto_limits_;
+    uint8_t field_presence_;
+    uint8_t enum_type_;
+    uint8_t repeated_field_encoding_;
+    uint8_t utf8_validation_;
+    uint8_t message_encoding_;
+    uint8_t json_format_;
+    uint8_t enforce_naming_style_;
+    uint8_t default_symbol_visibility_;
+    uint8_t enforce_proto_limits_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -3676,6 +3688,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -3695,6 +3708,7 @@
     bool repeated_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -3903,6 +3917,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -3919,6 +3934,7 @@
     ::int32_t end_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -4127,6 +4143,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -4143,6 +4160,7 @@
     ::int32_t end_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -4441,6 +4459,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -4462,6 +4481,7 @@
     double double_value_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -4863,6 +4883,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -4879,6 +4900,7 @@
     ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location > location_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -5085,6 +5107,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -5100,6 +5123,7 @@
     ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation > annotation_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -5333,6 +5357,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -5350,6 +5375,7 @@
     int edition_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -5778,6 +5804,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -5796,6 +5823,7 @@
     bool deprecated_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -6212,6 +6240,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -6229,6 +6258,7 @@
     ::google::protobuf::FeatureSet* PROTOBUF_NULLABLE features_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -6690,6 +6720,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -6706,9 +6737,10 @@
     ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
     ::google::protobuf::FeatureSet* PROTOBUF_NULLABLE features_;
     bool deprecated_;
-    int idempotency_level_;
+    uint8_t idempotency_level_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -7185,6 +7217,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -7207,6 +7240,7 @@
     ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -7922,6 +7956,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -7953,11 +7988,12 @@
     bool java_generate_equals_and_hash_;
     bool deprecated_;
     bool java_string_check_utf8_;
-    int optimize_for_;
+    uint8_t optimize_for_;
     bool cc_enable_arenas_;
     ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -8216,8 +8252,8 @@
     kPackedFieldNumber = 2,
     kDeprecatedFieldNumber = 3,
     kLazyFieldNumber = 5,
-    kWeakFieldNumber = 10,
     kJstypeFieldNumber = 6,
+    kWeakFieldNumber = 10,
     kUnverifiedLazyFieldNumber = 15,
     kDebugRedactFieldNumber = 16,
     kRetentionFieldNumber = 17,
@@ -8337,17 +8373,6 @@
   void _internal_set_lazy(bool value);
 
   public:
-  // optional bool weak = 10 [default = false, deprecated = true];
-  [[nodiscard]] [[deprecated]]  bool has_weak() const;
-  [[deprecated]]  void clear_weak() ;
-  [[nodiscard]] [[deprecated]] bool weak() const;
-  [[deprecated]] void set_weak(bool value);
-
-  private:
-  bool _internal_weak() const;
-  void _internal_set_weak(bool value);
-
-  public:
   // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
   [[nodiscard]] bool has_jstype() const;
   void clear_jstype() ;
@@ -8359,6 +8384,17 @@
   void _internal_set_jstype(::google::protobuf::FieldOptions_JSType value);
 
   public:
+  // optional bool weak = 10 [default = false, deprecated = true];
+  [[nodiscard]] [[deprecated]]  bool has_weak() const;
+  [[deprecated]]  void clear_weak() ;
+  [[nodiscard]] [[deprecated]] bool weak() const;
+  [[deprecated]] void set_weak(bool value);
+
+  private:
+  bool _internal_weak() const;
+  void _internal_set_weak(bool value);
+
+  public:
   // optional bool unverified_lazy = 15 [default = false];
   [[nodiscard]] bool has_unverified_lazy() const;
   void clear_unverified_lazy() ;
@@ -8633,6 +8669,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -8650,18 +8687,19 @@
     ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
     ::google::protobuf::FeatureSet* PROTOBUF_NULLABLE features_;
     ::google::protobuf::FieldOptions_FeatureSupport* PROTOBUF_NULLABLE feature_support_;
-    int ctype_;
+    uint8_t ctype_;
     bool packed_;
     bool deprecated_;
     bool lazy_;
+    uint8_t jstype_;
     bool weak_;
-    int jstype_;
     bool unverified_lazy_;
     bool debug_redact_;
-    int retention_;
+    uint8_t retention_;
     ::google::protobuf::RepeatedField<int> targets_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -8897,6 +8935,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -8914,6 +8953,7 @@
     int maximum_edition_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -9384,6 +9424,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -9400,9 +9441,10 @@
     ::google::protobuf::RepeatedPtrField< ::google::protobuf::ExtensionRangeOptions_Declaration > declaration_;
     ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
     ::google::protobuf::FeatureSet* PROTOBUF_NULLABLE features_;
-    int verification_;
+    uint8_t verification_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -9859,6 +9901,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -9879,6 +9922,7 @@
     bool debug_redact_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -10331,6 +10375,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -10351,6 +10396,7 @@
     ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -10573,6 +10619,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -10589,6 +10636,7 @@
     ::google::protobuf::OneofOptions* PROTOBUF_NULLABLE options_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -10869,6 +10917,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -10889,6 +10938,7 @@
     bool server_streaming_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -11296,6 +11346,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -11317,10 +11368,11 @@
     ::int32_t number_;
     ::int32_t oneof_index_;
     bool proto3_optional_;
-    int label_;
-    int type_;
+    uint8_t label_;
+    uint8_t type_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -11555,6 +11607,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -11572,6 +11625,7 @@
     ::int32_t number_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -11801,6 +11855,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -11818,6 +11873,7 @@
     ::int32_t end_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -12061,6 +12117,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -12078,6 +12135,7 @@
     ::google::protobuf::ServiceOptions* PROTOBUF_NULLABLE options_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -12382,6 +12440,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -12399,9 +12458,10 @@
     ::google::protobuf::RepeatedPtrField<::std::string> reserved_name_;
     ::google::protobuf::internal::ArenaStringPtr name_;
     ::google::protobuf::EnumOptions* PROTOBUF_NULLABLE options_;
-    int visibility_;
+    uint8_t visibility_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -12812,6 +12872,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -12834,9 +12895,10 @@
     ::google::protobuf::RepeatedPtrField<::std::string> reserved_name_;
     ::google::protobuf::internal::ArenaStringPtr name_;
     ::google::protobuf::MessageOptions* PROTOBUF_NULLABLE options_;
-    int visibility_;
+    uint8_t visibility_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -13299,6 +13361,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -13327,6 +13390,7 @@
     int edition_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -13727,6 +13791,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -13743,6 +13808,7 @@
     ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > file_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
 };
@@ -14725,7 +14791,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::Edition_internal_data_));
-                                          _impl_.edition_ = value;
+                                          _impl_.edition_ = static_cast<int>(value);
 }
 
 // -------------------------------------------------------------------
@@ -15609,7 +15675,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::SymbolVisibility_internal_data_));
-                                          _impl_.visibility_ = value;
+                                          _impl_.visibility_ = static_cast<uint8_t>(value);
 }
 
 // -------------------------------------------------------------------
@@ -16078,7 +16144,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::ExtensionRangeOptions_VerificationState_internal_data_));
-                                          _impl_.verification_ = value;
+                                          _impl_.verification_ = static_cast<uint8_t>(value);
 }
 
 // -------------------------------------------------------------------
@@ -16209,7 +16275,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::FieldDescriptorProto_Label_internal_data_));
-                                          _impl_.label_ = value;
+                                          _impl_.label_ = static_cast<uint8_t>(value);
 }
 
 // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
@@ -16240,7 +16306,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::FieldDescriptorProto_Type_internal_data_));
-                                          _impl_.type_ = value;
+                                          _impl_.type_ = static_cast<uint8_t>(value);
 }
 
 // optional string type_name = 6;
@@ -17282,7 +17348,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::SymbolVisibility_internal_data_));
-                                          _impl_.visibility_ = value;
+                                          _impl_.visibility_ = static_cast<uint8_t>(value);
 }
 
 // -------------------------------------------------------------------
@@ -18323,7 +18389,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::FileOptions_OptimizeMode_internal_data_));
-                                          _impl_.optimize_for_ = value;
+                                          _impl_.optimize_for_ = static_cast<uint8_t>(value);
 }
 
 // optional string go_package = 11;
@@ -19494,7 +19560,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::Edition_internal_data_));
-                                          _impl_.edition_ = value;
+                                          _impl_.edition_ = static_cast<int>(value);
 }
 
 // optional string value = 2;
@@ -19597,7 +19663,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::Edition_internal_data_));
-                                          _impl_.edition_introduced_ = value;
+                                          _impl_.edition_introduced_ = static_cast<int>(value);
 }
 
 // optional .google.protobuf.Edition edition_deprecated = 2;
@@ -19628,7 +19694,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::Edition_internal_data_));
-                                          _impl_.edition_deprecated_ = value;
+                                          _impl_.edition_deprecated_ = static_cast<int>(value);
 }
 
 // optional string deprecation_warning = 3;
@@ -19727,7 +19793,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::Edition_internal_data_));
-                                          _impl_.edition_removed_ = value;
+                                          _impl_.edition_removed_ = static_cast<int>(value);
 }
 
 // optional string removal_error = 5;
@@ -19830,7 +19896,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::FieldOptions_CType_internal_data_));
-                                          _impl_.ctype_ = value;
+                                          _impl_.ctype_ = static_cast<uint8_t>(value);
 }
 
 // optional bool packed = 2;
@@ -19863,13 +19929,13 @@
 
 // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
 inline bool FieldOptions::has_jstype() const {
-  bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000200U);
+  bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000100U);
   return value;
 }
 inline void FieldOptions::clear_jstype() {
   ::google::protobuf::internal::TSanWrite(&_impl_);
   _impl_.jstype_ = 0;
-  ClearHasBit(_impl_._has_bits_[0], 0x00000200U);
+  ClearHasBit(_impl_._has_bits_[0], 0x00000100U);
 }
 inline ::google::protobuf::FieldOptions_JSType FieldOptions::jstype() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.jstype)
@@ -19877,7 +19943,7 @@
 }
 inline void FieldOptions::set_jstype(::google::protobuf::FieldOptions_JSType value) {
   _internal_set_jstype(value);
-  SetHasBit(_impl_._has_bits_[0], 0x00000200U);
+  SetHasBit(_impl_._has_bits_[0], 0x00000100U);
   // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.jstype)
 }
 inline ::google::protobuf::FieldOptions_JSType FieldOptions::_internal_jstype() const {
@@ -19889,7 +19955,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::FieldOptions_JSType_internal_data_));
-                                          _impl_.jstype_ = value;
+                                          _impl_.jstype_ = static_cast<uint8_t>(value);
 }
 
 // optional bool lazy = 5 [default = false];
@@ -19978,13 +20044,13 @@
 
 // optional bool weak = 10 [default = false, deprecated = true];
 inline bool FieldOptions::has_weak() const {
-  bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000100U);
+  bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000200U);
   return value;
 }
 inline void FieldOptions::clear_weak() {
   ::google::protobuf::internal::TSanWrite(&_impl_);
   _impl_.weak_ = false;
-  ClearHasBit(_impl_._has_bits_[0], 0x00000100U);
+  ClearHasBit(_impl_._has_bits_[0], 0x00000200U);
 }
 inline bool FieldOptions::weak() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.weak)
@@ -19992,7 +20058,7 @@
 }
 inline void FieldOptions::set_weak(bool value) {
   _internal_set_weak(value);
-  SetHasBit(_impl_._has_bits_[0], 0x00000100U);
+  SetHasBit(_impl_._has_bits_[0], 0x00000200U);
   // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.weak)
 }
 inline bool FieldOptions::_internal_weak() const {
@@ -20060,7 +20126,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::FieldOptions_OptionRetention_internal_data_));
-                                          _impl_.retention_ = value;
+                                          _impl_.retention_ = static_cast<uint8_t>(value);
 }
 
 // repeated .google.protobuf.FieldOptions.OptionTargetType targets = 19;
@@ -21387,7 +21453,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::MethodOptions_IdempotencyLevel_internal_data_));
-                                          _impl_.idempotency_level_ = value;
+                                          _impl_.idempotency_level_ = static_cast<uint8_t>(value);
 }
 
 // optional .google.protobuf.FeatureSet features = 35;
@@ -22032,7 +22098,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::FeatureSet_FieldPresence_internal_data_));
-                                          _impl_.field_presence_ = value;
+                                          _impl_.field_presence_ = static_cast<uint8_t>(value);
 }
 
 // optional .google.protobuf.FeatureSet.EnumType enum_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = {
@@ -22063,7 +22129,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::FeatureSet_EnumType_internal_data_));
-                                          _impl_.enum_type_ = value;
+                                          _impl_.enum_type_ = static_cast<uint8_t>(value);
 }
 
 // optional .google.protobuf.FeatureSet.RepeatedFieldEncoding repeated_field_encoding = 3 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
@@ -22094,7 +22160,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::FeatureSet_RepeatedFieldEncoding_internal_data_));
-                                          _impl_.repeated_field_encoding_ = value;
+                                          _impl_.repeated_field_encoding_ = static_cast<uint8_t>(value);
 }
 
 // optional .google.protobuf.FeatureSet.Utf8Validation utf8_validation = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
@@ -22125,7 +22191,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::FeatureSet_Utf8Validation_internal_data_));
-                                          _impl_.utf8_validation_ = value;
+                                          _impl_.utf8_validation_ = static_cast<uint8_t>(value);
 }
 
 // optional .google.protobuf.FeatureSet.MessageEncoding message_encoding = 5 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = {
@@ -22156,7 +22222,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::FeatureSet_MessageEncoding_internal_data_));
-                                          _impl_.message_encoding_ = value;
+                                          _impl_.message_encoding_ = static_cast<uint8_t>(value);
 }
 
 // optional .google.protobuf.FeatureSet.JsonFormat json_format = 6 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = {
@@ -22187,7 +22253,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::FeatureSet_JsonFormat_internal_data_));
-                                          _impl_.json_format_ = value;
+                                          _impl_.json_format_ = static_cast<uint8_t>(value);
 }
 
 // optional .google.protobuf.FeatureSet.EnforceNamingStyle enforce_naming_style = 7 [retention = RETENTION_SOURCE, targets = TARGET_TYPE_FILE, targets = TARGET_TYPE_EXTENSION_RANGE, targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_ONEOF, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_ENUM_ENTRY, targets = TARGET_TYPE_SERVICE, targets = TARGET_TYPE_METHOD, edition_defaults = {
@@ -22218,7 +22284,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::FeatureSet_EnforceNamingStyle_internal_data_));
-                                          _impl_.enforce_naming_style_ = value;
+                                          _impl_.enforce_naming_style_ = static_cast<uint8_t>(value);
 }
 
 // optional .google.protobuf.FeatureSet.VisibilityFeature.DefaultSymbolVisibility default_symbol_visibility = 8 [retention = RETENTION_SOURCE, targets = TARGET_TYPE_FILE, edition_defaults = {
@@ -22249,7 +22315,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::FeatureSet_VisibilityFeature_DefaultSymbolVisibility_internal_data_));
-                                          _impl_.default_symbol_visibility_ = value;
+                                          _impl_.default_symbol_visibility_ = static_cast<uint8_t>(value);
 }
 
 // optional .google.protobuf.FeatureSet.ProtoLimitsFeature.EnforceProtoLimits enforce_proto_limits = 9 [retention = RETENTION_SOURCE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_ONEOF, edition_defaults = {
@@ -22280,7 +22346,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::FeatureSet_ProtoLimitsFeature_EnforceProtoLimits_internal_data_));
-                                          _impl_.enforce_proto_limits_ = value;
+                                          _impl_.enforce_proto_limits_ = static_cast<uint8_t>(value);
 }
 
 // -------------------------------------------------------------------
@@ -22315,7 +22381,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::Edition_internal_data_));
-                                          _impl_.edition_ = value;
+                                          _impl_.edition_ = static_cast<int>(value);
 }
 
 // optional .google.protobuf.FeatureSet overridable_features = 4;
@@ -22602,7 +22668,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::Edition_internal_data_));
-                                          _impl_.minimum_edition_ = value;
+                                          _impl_.minimum_edition_ = static_cast<int>(value);
 }
 
 // optional .google.protobuf.Edition maximum_edition = 5;
@@ -22633,7 +22699,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::Edition_internal_data_));
-                                          _impl_.maximum_edition_ = value;
+                                          _impl_.maximum_edition_ = static_cast<int>(value);
 }
 
 // -------------------------------------------------------------------
@@ -23221,7 +23287,7 @@
 
                                           assert(::google::protobuf::internal::ValidateEnum(
                                               value, ::google::protobuf::GeneratedCodeInfo_Annotation_Semantic_internal_data_));
-                                          _impl_.semantic_ = value;
+                                          _impl_.semantic_ = static_cast<uint8_t>(value);
 }
 
 // -------------------------------------------------------------------
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index 83a026b..ddd325b 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -993,8 +993,19 @@
     SWAP_VALUES(FLOAT, float);
     SWAP_VALUES(DOUBLE, double);
     SWAP_VALUES(BOOL, bool);
-    SWAP_VALUES(ENUM, int);
 #undef SWAP_VALUES
+    case FieldDescriptor::CPPTYPE_ENUM:
+      if (r->schema_.IsEnum8(field)) {
+        std::swap(*r->MutableRaw<uint8_t>(lhs, field),
+                  *r->MutableRaw<uint8_t>(rhs, field));
+      } else if (r->schema_.IsEnum16(field)) {
+        std::swap(*r->MutableRaw<uint16_t>(lhs, field),
+                  *r->MutableRaw<uint16_t>(rhs, field));
+      } else {
+        std::swap(*r->MutableRaw<int>(lhs, field),
+                  *r->MutableRaw<int>(rhs, field));
+      }
+      break;
     default:
       ABSL_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
   }
@@ -1617,8 +1628,26 @@
 #undef CLEAR_TYPE
 
       case FieldDescriptor::CPPTYPE_ENUM:
-        *MutableRaw<int>(message, field) =
-            field->default_value_enum()->number();
+        if (schema_.IsEnum8(field)) {
+          if (schema_.IsEnumSigned(field)) {
+            *MutableRaw<int8_t>(message, field) =
+                static_cast<int8_t>(field->default_value_enum()->number());
+          } else {
+            *MutableRaw<uint8_t>(message, field) =
+                static_cast<uint8_t>(field->default_value_enum()->number());
+          }
+        } else if (schema_.IsEnum16(field)) {
+          if (schema_.IsEnumSigned(field)) {
+            *MutableRaw<int16_t>(message, field) =
+                static_cast<int16_t>(field->default_value_enum()->number());
+          } else {
+            *MutableRaw<uint16_t>(message, field) =
+                static_cast<uint16_t>(field->default_value_enum()->number());
+          }
+        } else {
+          *MutableRaw<int>(message, field) =
+              field->default_value_enum()->number();
+        }
         break;
 
       case FieldDescriptor::CPPTYPE_STRING: {
@@ -2433,6 +2462,18 @@
         field->number(), field->default_value_enum()->number());
   } else if (schema_.InRealOneof(field) && !HasOneofField(message, field)) {
     value = field->default_value_enum()->number();
+  } else if (schema_.IsEnum8(field)) {
+    if (schema_.IsEnumSigned(field)) {
+      value = GetField<int8_t>(message, field);
+    } else {
+      value = GetField<uint8_t>(message, field);
+    }
+  } else if (schema_.IsEnum16(field)) {
+    if (schema_.IsEnumSigned(field)) {
+      value = GetField<int16_t>(message, field);
+    } else {
+      value = GetField<uint16_t>(message, field);
+    }
   } else {
     value = GetField<int>(message, field);
   }
@@ -2468,6 +2509,18 @@
   if (field->is_extension()) {
     MutableExtensionSet(message)->Set<int>(message->GetArena(), field->number(),
                                            field->type(), value, field);
+  } else if (schema_.IsEnum8(field)) {
+    if (schema_.IsEnumSigned(field)) {
+      SetField<int8_t>(message, field, static_cast<int8_t>(value));
+    } else {
+      SetField<uint8_t>(message, field, static_cast<uint8_t>(value));
+    }
+  } else if (schema_.IsEnum16(field)) {
+    if (schema_.IsEnumSigned(field)) {
+      SetField<int16_t>(message, field, static_cast<int16_t>(value));
+    } else {
+      SetField<uint16_t>(message, field, static_cast<uint16_t>(value));
+    }
   } else {
     SetField<int>(message, field, value);
   }
@@ -3245,6 +3298,11 @@
                     "Code assumes uint64_t and double are the same size.");
       return absl::bit_cast<uint64_t>(GetRaw<double>(message, field)) != 0;
     case FieldDescriptor::CPPTYPE_ENUM:
+      if (schema_.IsEnum8(field)) {
+        return GetRaw<uint8_t>(message, field) != 0;
+      } else if (schema_.IsEnum16(field)) {
+        return GetRaw<uint16_t>(message, field) != 0;
+      }
       return GetRaw<int>(message, field) != 0;
     case FieldDescriptor::CPPTYPE_STRING:
       switch (field->cpp_string_type()) {
@@ -3795,6 +3853,13 @@
       }
       return std::monostate{};
     };
+    const auto enum_rep = [&]() -> FieldOptions::EnumRep {
+      if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+        if (schema_.IsEnum8(field)) return FieldOptions::kEnum8;
+        if (schema_.IsEnum16(field)) return FieldOptions::kEnum16;
+      }
+      return FieldOptions::kEnum32;
+    };
     fields.push_back({
         field,  //
         static_cast<int>(schema_.HasBitIndex(field)),
@@ -3807,6 +3872,7 @@
         /* use_direct_tcparser_table */ false,
         schema_.IsSplit(field),
         str_options(),
+        enum_rep(),
     });
   }
   std::sort(fields.begin(), fields.end(), [](const auto& a, const auto& b) {
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index 3cf3458..ff4ffb1 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -65,10 +65,14 @@
 inline constexpr uint32_t kLazyOffsetTag = 0x40000000u;
 inline constexpr uint32_t kInlinedOffsetTag = 0x40000000u;
 inline constexpr uint32_t kMicroStringOffsetTag = 0x20000000u;
+inline constexpr uint32_t kEnum8OffsetTag = 0x20000000u;
+inline constexpr uint32_t kEnum16OffsetTag = 0x40000000u;
+inline constexpr uint32_t kEnumSignedOffsetTag = 0x10000000u;
 
-inline constexpr uint32_t kAllOffsetTags = kSplitFieldOffsetTag |
-                                           kLazyOffsetTag | kInlinedOffsetTag |
-                                           kMicroStringOffsetTag;
+inline constexpr uint32_t kAllOffsetTags =
+    kSplitFieldOffsetTag | kLazyOffsetTag | kInlinedOffsetTag |
+    kMicroStringOffsetTag | kEnum8OffsetTag | kEnum16OffsetTag |
+    kEnumSignedOffsetTag;
 
 // Structs that the code generator emits directly to describe a message.
 // These should never used directly except to build a ReflectionSchema
@@ -158,6 +162,18 @@
     return IsMicroString(offsets_[field->index()], field->type());
   }
 
+  bool IsEnum8(const FieldDescriptor* field) const {
+    return IsEnum8(offsets_[field->index()], field->type());
+  }
+
+  bool IsEnum16(const FieldDescriptor* field) const {
+    return IsEnum16(offsets_[field->index()], field->type());
+  }
+
+  bool IsEnumSigned(const FieldDescriptor* field) const {
+    return IsEnumSigned(offsets_[field->index()], field->type());
+  }
+
   uint32_t GetOneofCaseOffset(const OneofDescriptor* oneof_descriptor) const {
     return static_cast<uint32_t>(oneof_case_offset_) +
            static_cast<uint32_t>(
@@ -263,6 +279,19 @@
     return (v & kMicroStringOffsetTag) != 0u;
   }
 
+  static bool IsEnum8(uint32_t v, FieldDescriptor::Type type) {
+    return type == FieldDescriptor::TYPE_ENUM && (v & kEnum8OffsetTag) != 0u;
+  }
+
+  static bool IsEnum16(uint32_t v, FieldDescriptor::Type type) {
+    return type == FieldDescriptor::TYPE_ENUM && (v & kEnum16OffsetTag) != 0u;
+  }
+
+  static bool IsEnumSigned(uint32_t v, FieldDescriptor::Type type) {
+    return type == FieldDescriptor::TYPE_ENUM &&
+           (v & kEnumSignedOffsetTag) != 0u;
+  }
+
   const Message* default_instance_;
   const uint32_t* offsets_;
   const uint32_t* has_bit_indices_;
diff --git a/src/google/protobuf/generated_message_reflection_unittest.cc b/src/google/protobuf/generated_message_reflection_unittest.cc
index e76f927..6ce06e2 100644
--- a/src/google/protobuf/generated_message_reflection_unittest.cc
+++ b/src/google/protobuf/generated_message_reflection_unittest.cc
@@ -22,6 +22,8 @@
 #include "google/protobuf/generated_message_reflection.h"
 
 #include <cstddef>
+#include <cstdint>
+#include <cstring>
 #include <memory>
 #include <string>
 #include <vector>
@@ -81,6 +83,21 @@
     const Reflection* reflection = msg.GetReflection();
     return reflection->GetRaw<T>(msg, field);
   }
+  static std::unique_ptr<Reflection> CreateReflection(
+      const Descriptor* descriptor, const internal::ReflectionSchema& schema,
+      const DescriptorPool* pool, MessageFactory* factory) {
+    return std::unique_ptr<Reflection>(
+        new Reflection(descriptor, schema, pool, factory));
+  }
+  static void SetEnumValueInternal(const Reflection* reflection,
+                                   Message* message,
+                                   const FieldDescriptor* field, int value) {
+    reflection->SetEnumValueInternal(message, field, value);
+  }
+  static uint32_t GetFieldOffset(const Reflection* reflection,
+                                 const FieldDescriptor* field) {
+    return reflection->schema_.GetFieldOffset(field);
+  }
 };
 
 namespace {
@@ -2043,6 +2060,69 @@
             "cpp.file.options.test");
 }
 
+TEST(GeneratedMessageReflection, Enum8And16BitFields) {
+  const Descriptor* desc = unittest::TestAllTypes::descriptor();
+  const FieldDescriptor* field = desc->FindFieldByName("optional_nested_enum");
+  ASSERT_NE(field, nullptr);
+
+  std::vector<uint32_t> offsets(desc->field_count(), 0);
+  std::vector<uint32_t> has_bits(desc->field_count(), 0);
+
+  // Test 8-bit unsigned enum
+  {
+    offsets[field->index()] = 100 | internal::kEnum8OffsetTag;
+    internal::ReflectionSchema schema(
+        &unittest::TestAllTypes::default_instance(), offsets.data(),
+        has_bits.data(), /*has_bits_offset=*/-1, /*extensions_offset=*/-1,
+        /*oneof_case_offset=*/-1, sizeof(unittest::TestAllTypes),
+        /*split_offset=*/-1, /*sizeof_split=*/-1);
+    EXPECT_TRUE(schema.IsEnum8(field));
+    EXPECT_FALSE(schema.IsEnum16(field));
+    EXPECT_FALSE(schema.IsEnumSigned(field));
+  }
+
+  // Test 8-bit signed enum
+  {
+    offsets[field->index()] =
+        100 | internal::kEnum8OffsetTag | internal::kEnumSignedOffsetTag;
+    internal::ReflectionSchema schema(
+        &unittest::TestAllTypes::default_instance(), offsets.data(),
+        has_bits.data(), /*has_bits_offset=*/-1, /*extensions_offset=*/-1,
+        /*oneof_case_offset=*/-1, sizeof(unittest::TestAllTypes),
+        /*split_offset=*/-1, /*sizeof_split=*/-1);
+    EXPECT_TRUE(schema.IsEnum8(field));
+    EXPECT_FALSE(schema.IsEnum16(field));
+    EXPECT_TRUE(schema.IsEnumSigned(field));
+  }
+
+  // Test 16-bit unsigned enum
+  {
+    offsets[field->index()] = 100 | internal::kEnum16OffsetTag;
+    internal::ReflectionSchema schema(
+        &unittest::TestAllTypes::default_instance(), offsets.data(),
+        has_bits.data(), /*has_bits_offset=*/-1, /*extensions_offset=*/-1,
+        /*oneof_case_offset=*/-1, sizeof(unittest::TestAllTypes),
+        /*split_offset=*/-1, /*sizeof_split=*/-1);
+    EXPECT_FALSE(schema.IsEnum8(field));
+    EXPECT_TRUE(schema.IsEnum16(field));
+    EXPECT_FALSE(schema.IsEnumSigned(field));
+  }
+
+  // Test 16-bit signed enum
+  {
+    offsets[field->index()] =
+        100 | internal::kEnum16OffsetTag | internal::kEnumSignedOffsetTag;
+    internal::ReflectionSchema schema(
+        &unittest::TestAllTypes::default_instance(), offsets.data(),
+        has_bits.data(), /*has_bits_offset=*/-1, /*extensions_offset=*/-1,
+        /*oneof_case_offset=*/-1, sizeof(unittest::TestAllTypes),
+        /*split_offset=*/-1, /*sizeof_split=*/-1);
+    EXPECT_FALSE(schema.IsEnum8(field));
+    EXPECT_TRUE(schema.IsEnum16(field));
+    EXPECT_TRUE(schema.IsEnumSigned(field));
+  }
+}
+
 }  // namespace
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/generated_message_tctable_gen.cc b/src/google/protobuf/generated_message_tctable_gen.cc
index f8d82ac..9bdda8e 100644
--- a/src/google/protobuf/generated_message_tctable_gen.cc
+++ b/src/google/protobuf/generated_message_tctable_gen.cc
@@ -190,22 +190,46 @@
       picked = PROTOBUF_PICK_PACKABLE_FUNCTION(kFastF64);
       break;
     case FieldDescriptor::TYPE_ENUM:
-      if (TreatEnumAsInt(field)) {
-        picked = PROTOBUF_PICK_PACKABLE_FUNCTION(kFastV32);
+      if (options.is_enum_8()) {
+        if (TreatEnumAsInt(field)) {
+          picked = PROTOBUF_PICK_PACKABLE_FUNCTION(kFastV8);
+        } else {
+          int32_t first, last;
+          if (GetEnumValidationRange(field->enum_type(), first, last)) {
+            picked = PROTOBUF_PICK_PACKABLE_FUNCTION(kFastEr8);
+          } else {
+            picked = PROTOBUF_PICK_PACKABLE_FUNCTION(kFastEv8);
+          }
+        }
+      } else if (options.is_enum_16()) {
+        if (TreatEnumAsInt(field)) {
+          picked = PROTOBUF_PICK_PACKABLE_FUNCTION(kFastV16);
+        } else {
+          int32_t first, last;
+          if (GetEnumValidationRange(field->enum_type(), first, last)) {
+            picked = PROTOBUF_PICK_PACKABLE_FUNCTION(kFastEr16);
+          } else {
+            picked = PROTOBUF_PICK_PACKABLE_FUNCTION(kFastEv16);
+          }
+        }
       } else {
-        switch (GetEnumRangeInfo(field, info.aux_idx)) {
-          case EnumRangeInfo::kNone:
-            picked = PROTOBUF_PICK_PACKABLE_FUNCTION(kFastEv);
-            break;
-          case EnumRangeInfo::kContiguous:
-            picked = PROTOBUF_PICK_PACKABLE_FUNCTION(kFastEr);
-            break;
-          case EnumRangeInfo::kContiguous0:
-            picked = PROTOBUF_PICK_PACKABLE_FUNCTION(kFastEr0);
-            break;
-          case EnumRangeInfo::kContiguous1:
-            picked = PROTOBUF_PICK_PACKABLE_FUNCTION(kFastEr1);
-            break;
+        if (TreatEnumAsInt(field)) {
+          picked = PROTOBUF_PICK_PACKABLE_FUNCTION(kFastV32);
+        } else {
+          switch (GetEnumRangeInfo(field, info.aux_idx)) {
+            case EnumRangeInfo::kNone:
+              picked = PROTOBUF_PICK_PACKABLE_FUNCTION(kFastEv);
+              break;
+            case EnumRangeInfo::kContiguous:
+              picked = PROTOBUF_PICK_PACKABLE_FUNCTION(kFastEr);
+              break;
+            case EnumRangeInfo::kContiguous0:
+              picked = PROTOBUF_PICK_PACKABLE_FUNCTION(kFastEr0);
+              break;
+            case EnumRangeInfo::kContiguous1:
+              picked = PROTOBUF_PICK_PACKABLE_FUNCTION(kFastEr1);
+              break;
+          }
         }
       }
       break;
@@ -255,6 +279,10 @@
     return false;
   }
 
+  if (field->is_repeated() && (options.is_enum_8() || options.is_enum_16())) {
+    return false;
+  }
+
   if (HasLazyRep(field, options) && !message_options.uses_codegen) {
     // Can't use TDP on lazy fields if we can't do codegen.
     return false;
@@ -548,24 +576,62 @@
                                                               : fl::kBool;
       break;
     case FieldDescriptor::TYPE_ENUM:
-      if (TreatEnumAsInt(field)) {
-        // No validation is required.
-        type_card |= field->is_repeated() && field->is_packed()
-                         ? fl::kPackedOpenEnum
-                         : fl::kOpenEnum;
-      } else {
-        int32_t first;
-        int32_t last;
-        if (GetEnumValidationRange(field->enum_type(), first, last)) {
-          // Validation is done by range check (start/length in FieldAux).
+      if (options.is_enum_8()) {
+        if (TreatEnumAsInt(field)) {
           type_card |= field->is_repeated() && field->is_packed()
-                           ? fl::kPackedEnumRange
-                           : fl::kEnumRange;
+                           ? fl::kPackedOpenEnum8
+                           : fl::kOpenEnum8;
         } else {
-          // Validation uses the generated _IsValid function.
+          int32_t first;
+          int32_t last;
+          if (GetEnumValidationRange(field->enum_type(), first, last)) {
+            type_card |= field->is_repeated() && field->is_packed()
+                             ? fl::kPackedEnumRange8
+                             : fl::kEnumRange8;
+          } else {
+            type_card |= field->is_repeated() && field->is_packed()
+                             ? fl::kPackedEnum8
+                             : fl::kEnum8;
+          }
+        }
+      } else if (options.is_enum_16()) {
+        if (TreatEnumAsInt(field)) {
           type_card |= field->is_repeated() && field->is_packed()
-                           ? fl::kPackedEnum
-                           : fl::kEnum;
+                           ? fl::kPackedOpenEnum16
+                           : fl::kOpenEnum16;
+        } else {
+          int32_t first;
+          int32_t last;
+          if (GetEnumValidationRange(field->enum_type(), first, last)) {
+            type_card |= field->is_repeated() && field->is_packed()
+                             ? fl::kPackedEnumRange16
+                             : fl::kEnumRange16;
+          } else {
+            type_card |= field->is_repeated() && field->is_packed()
+                             ? fl::kPackedEnum16
+                             : fl::kEnum16;
+          }
+        }
+      } else {
+        if (TreatEnumAsInt(field)) {
+          // No validation is required.
+          type_card |= field->is_repeated() && field->is_packed()
+                           ? fl::kPackedOpenEnum
+                           : fl::kOpenEnum;
+        } else {
+          int32_t first;
+          int32_t last;
+          if (GetEnumValidationRange(field->enum_type(), first, last)) {
+            // Validation is done by range check (start/length in FieldAux).
+            type_card |= field->is_repeated() && field->is_packed()
+                             ? fl::kPackedEnumRange
+                             : fl::kEnumRange;
+          } else {
+            // Validation uses the generated _IsValid function.
+            type_card |= field->is_repeated() && field->is_packed()
+                             ? fl::kPackedEnum
+                             : fl::kEnum;
+          }
         }
       }
       break;
diff --git a/src/google/protobuf/generated_message_tctable_gen.h b/src/google/protobuf/generated_message_tctable_gen.h
index fd1e0e6..e7e55bd 100644
--- a/src/google/protobuf/generated_message_tctable_gen.h
+++ b/src/google/protobuf/generated_message_tctable_gen.h
@@ -86,6 +86,11 @@
 
     using StrOptions = std::variant<std::monostate, StringInlined, MicroString>;
     StrOptions str_options;
+
+    enum EnumRep { kEnum32 = 0, kEnum8, kEnum16 };
+    EnumRep enum_rep = kEnum32;
+    bool is_enum_8() const { return enum_rep == kEnum8; }
+    bool is_enum_16() const { return enum_rep == kEnum16; }
   };
 
   struct FieldEntryInfo;
diff --git a/src/google/protobuf/generated_message_tctable_impl.h b/src/google/protobuf/generated_message_tctable_impl.h
index 34a2a82..ea9a4cc 100644
--- a/src/google/protobuf/generated_message_tctable_impl.h
+++ b/src/google/protobuf/generated_message_tctable_impl.h
@@ -127,6 +127,7 @@
 
   // Numeric types (used for optional and repeated fields):
   kRep8Bits    = 0,
+  kRep16Bits   = 1 << kRepShift,
   kRep32Bits   = 2 << kRepShift,
   kRep64Bits   = 3 << kRepShift,
   // String types:
@@ -201,6 +202,14 @@
   // Numeric types:
   kBool            = 0 | kFkVarint | kRep8Bits,
 
+  kEnum8           = 0 | kFkVarint | kRep8Bits  | kFmtEnum   | kTvEnum,
+  kEnumRange8      = 0 | kFkVarint | kRep8Bits  | kFmtEnum   | kTvRange,
+  kOpenEnum8       = 0 | kFkVarint | kRep8Bits  | kFmtEnum,
+
+  kEnum16          = 0 | kFkVarint | kRep16Bits | kFmtEnum   | kTvEnum,
+  kEnumRange16     = 0 | kFkVarint | kRep16Bits | kFmtEnum   | kTvRange,
+  kOpenEnum16      = 0 | kFkVarint | kRep16Bits | kFmtEnum,
+
   kFixed32         = 0 | kFkFixed  | kRep32Bits | kFmtUnsigned,
   kUInt32          = 0 | kFkVarint | kRep32Bits | kFmtUnsigned,
   kSFixed32        = 0 | kFkFixed  | kRep32Bits | kFmtSigned,
@@ -220,6 +229,14 @@
 
   kPackedBool      = 0 | kFkPackedVarint | kRep8Bits,
 
+  kPackedEnum8     = 0 | kFkPackedVarint | kRep8Bits  | kFmtEnum   | kTvEnum,
+  kPackedEnumRange8 = 0 | kFkPackedVarint | kRep8Bits | kFmtEnum   | kTvRange,
+  kPackedOpenEnum8 = 0 | kFkPackedVarint | kRep8Bits  | kFmtEnum,
+
+  kPackedEnum16    = 0 | kFkPackedVarint | kRep16Bits | kFmtEnum   | kTvEnum,
+  kPackedEnumRange16 = 0 | kFkPackedVarint | kRep16Bits | kFmtEnum | kTvRange,
+  kPackedOpenEnum16 = 0 | kFkPackedVarint | kRep16Bits | kFmtEnum,
+
   kPackedFixed32   = 0 | kFkPackedFixed  | kRep32Bits | kFmtUnsigned,
   kPackedUInt32    = 0 | kFkPackedVarint | kRep32Bits | kFmtUnsigned,
   kPackedSFixed32  = 0 | kFkPackedFixed  | kRep32Bits | kFmtSigned,
@@ -251,6 +268,8 @@
 }  // namespace field_layout
 
 #ifndef NDEBUG
+[[noreturn]] PROTOBUF_EXPORT void AlignFail(std::integral_constant<size_t, 2>,
+                                            std::uintptr_t address);
 [[noreturn]] PROTOBUF_EXPORT void AlignFail(std::integral_constant<size_t, 4>,
                                             std::uintptr_t address);
 [[noreturn]] PROTOBUF_EXPORT void AlignFail(std::integral_constant<size_t, 8>,
@@ -334,6 +353,7 @@
 #define PROTOBUF_TC_PARSE_FUNCTION_LIST                           \
   /* These functions have the Fast entry ABI */                   \
   PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastV8)                  \
+  PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastV16)                 \
   PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastV32)                 \
   PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastV64)                 \
   PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastZ32)                 \
@@ -344,6 +364,10 @@
   PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastEr)                  \
   PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastEr0)                 \
   PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastEr1)                 \
+  PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastEv8)                 \
+  PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastEr8)                 \
+  PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastEv16)                \
+  PROTOBUF_TC_PARSE_FUNCTION_LIST_PACKED(FastEr16)                \
   PROTOBUF_TC_PARSE_FUNCTION_LIST_REPEATED(FastB)                 \
   PROTOBUF_TC_PARSE_FUNCTION_LIST_REPEATED(FastU)                 \
   PROTOBUF_TC_PARSE_FUNCTION_LIST_SINGLE(FastBi)                  \
@@ -481,6 +505,18 @@
       PROTOBUF_TC_PARAM_DECL);
   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV8P2(
       PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV16S1(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV16S2(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV16R1(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV16R2(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV16P1(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV16P2(
+      PROTOBUF_TC_PARAM_DECL);
   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV32S1(
       PROTOBUF_TC_PARAM_DECL);
   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV32S2(
@@ -537,14 +573,17 @@
     if (sizeof(FieldType) == 1) {
       return &FastV8S1;
     }
+    if (sizeof(FieldType) == 2) {
+      return &FastV16S1;
+    }
     if (sizeof(FieldType) == 4) {
       return &FastV32S1;
     }
     if (sizeof(FieldType) == 8) {
       return &FastV64S1;
     }
-    static_assert(sizeof(FieldType) == 1 || sizeof(FieldType) == 4 ||
-                      sizeof(FieldType) == 8,
+    static_assert(sizeof(FieldType) == 1 || sizeof(FieldType) == 2 ||
+                      sizeof(FieldType) == 4 || sizeof(FieldType) == 8,
                   "");
     ABSL_LOG(FATAL) << "This should be unreachable";
   }
@@ -604,6 +643,56 @@
   PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr1P2(
       PROTOBUF_TC_PARAM_DECL);
 
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr8S1(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr8S2(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr8R1(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr8R2(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr8P1(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr8P2(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEv8S1(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEv8S2(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEv8R1(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEv8R2(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEv8P1(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEv8P2(
+      PROTOBUF_TC_PARAM_DECL);
+
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr16S1(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr16S2(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr16R1(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr16R2(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr16P1(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr16P2(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEv16S1(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEv16S2(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEv16R1(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEv16R2(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEv16P1(
+      PROTOBUF_TC_PARAM_DECL);
+  PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEv16P2(
+      PROTOBUF_TC_PARAM_DECL);
+
   // Functions referenced by generated fast tables (string types):
   //   B: bytes      U: UTF-8 string
   //   (empty): ArenaStringPtr   i: InlinedString   c: Cord   m: MicroString
@@ -972,7 +1061,7 @@
       PROTOBUF_TC_PARAM_DECL);
 
   // Implementations for fast enum field parsing functions:
-  template <typename TagType, uint16_t xform_val>
+  template <typename FieldType, typename TagType, uint16_t xform_val>
   PROTOBUF_CC static inline const char* SingularEnum(PROTOBUF_TC_PARAM_DECL);
   template <typename TagType, uint8_t min>
   PROTOBUF_CC static inline const char* SingularEnumSmallRange(
diff --git a/src/google/protobuf/generated_message_tctable_lite.cc b/src/google/protobuf/generated_message_tctable_lite.cc
index c4c9023..2ca5d58 100644
--- a/src/google/protobuf/generated_message_tctable_lite.cc
+++ b/src/google/protobuf/generated_message_tctable_lite.cc
@@ -64,6 +64,10 @@
 //////////////////////////////////////////////////////////////////////////////
 
 #ifndef NDEBUG
+[[noreturn]] void AlignFail(std::integral_constant<size_t, 2>,
+                            std::uintptr_t address) {
+  ABSL_LOG(FATAL) << "Unaligned (2) access at " << address;
+}
 [[noreturn]] void AlignFail(std::integral_constant<size_t, 4>,
                             std::uintptr_t address) {
   ABSL_LOG(FATAL) << "Unaligned (4) access at " << address;
@@ -140,8 +144,14 @@
         if (has_bit) break;
         switch (entry.type_card & fl::kRepMask) {
           case fl::kRep8Bits:
-            if (RefAt<bool>(base, entry.offset) !=
-                RefAt<bool>(default_base, entry.offset)) {
+            if (RefAt<uint8_t>(base, entry.offset) !=
+                RefAt<uint8_t>(default_base, entry.offset)) {
+              return make_error_status();
+            }
+            break;
+          case fl::kRep16Bits:
+            if (RefAt<uint16_t>(base, entry.offset) !=
+                RefAt<uint16_t>(default_base, entry.offset)) {
               return make_error_status();
             }
             break;
@@ -240,6 +250,7 @@
                                                          msg, is_split);
           return repeated_field.empty();
         }
+        case fl::kRep16Bits:
         case fl::kRep32Bits: {
           const auto& repeated_field =
               GetRepeatedFieldAt<RepeatedField<uint32_t>>(base, entry.offset,
@@ -1243,6 +1254,26 @@
 PROTOBUF_NOINLINE const char* TcParser::FastV8P2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return PackedVarint<bool, uint16_t>(PROTOBUF_TC_PARAM_PASS);
 }
+PROTOBUF_NOINLINE const char* TcParser::FastV16S1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularVarint<uint16_t, uint8_t>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastV16S2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularVarint<uint16_t, uint16_t>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastV16R1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastV32R1(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastV16R2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastV32R2(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastV16P1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastV32P1(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastV16P2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastV32P2(PROTOBUF_TC_PARAM_PASS);
+}
 PROTOBUF_NOINLINE const char* TcParser::FastV32P1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return PackedVarint<uint32_t, uint8_t>(
       PROTOBUF_TC_PARAM_PASS);
@@ -1313,7 +1344,7 @@
   PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_NO_DATA_PASS);
 }
 
-template <typename TagType, uint16_t xform_val>
+template <typename FieldType, typename TagType, uint16_t xform_val>
 PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularEnum(
     PROTOBUF_TC_PARAM_DECL) {
   if (ABSL_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) {
@@ -1334,24 +1365,70 @@
     PROTOBUF_MUSTTAIL return FastUnknownEnumFallback(PROTOBUF_TC_PARAM_PASS);
   }
   SetCachedHasBit(hasbits, data.hasbit_idx());
-  RefAt<int32_t>(msg, data.offset()) = tmp;
+  RefAt<FieldType>(msg, data.offset()) = static_cast<FieldType>(tmp);
   PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_NO_DATA_PASS);
 }
 
 PROTOBUF_NOINLINE const char* TcParser::FastErS1(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return SingularEnum<uint8_t, field_layout::kTvRange>(
+  PROTOBUF_MUSTTAIL return SingularEnum<int32_t, uint8_t,
+                                        field_layout::kTvRange>(
       PROTOBUF_TC_PARAM_PASS);
 }
 PROTOBUF_NOINLINE const char* TcParser::FastErS2(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return SingularEnum<uint16_t, field_layout::kTvRange>(
+  PROTOBUF_MUSTTAIL return SingularEnum<int32_t, uint16_t,
+                                        field_layout::kTvRange>(
       PROTOBUF_TC_PARAM_PASS);
 }
 PROTOBUF_NOINLINE const char* TcParser::FastEvS1(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return SingularEnum<uint8_t, field_layout::kTvEnum>(
+  PROTOBUF_MUSTTAIL return SingularEnum<int32_t, uint8_t,
+                                        field_layout::kTvEnum>(
       PROTOBUF_TC_PARAM_PASS);
 }
 PROTOBUF_NOINLINE const char* TcParser::FastEvS2(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return SingularEnum<uint16_t, field_layout::kTvEnum>(
+  PROTOBUF_MUSTTAIL return SingularEnum<int32_t, uint16_t,
+                                        field_layout::kTvEnum>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastEr8S1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularEnum<uint8_t, uint8_t,
+                                        field_layout::kTvRange>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEr8S2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularEnum<uint8_t, uint16_t,
+                                        field_layout::kTvRange>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEv8S1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularEnum<uint8_t, uint8_t,
+                                        field_layout::kTvEnum>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEv8S2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularEnum<uint8_t, uint16_t,
+                                        field_layout::kTvEnum>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastEr16S1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularEnum<uint16_t, uint8_t,
+                                        field_layout::kTvRange>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEr16S2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularEnum<uint16_t, uint16_t,
+                                        field_layout::kTvRange>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEv16S1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularEnum<uint16_t, uint8_t,
+                                        field_layout::kTvEnum>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEv16S2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularEnum<uint16_t, uint16_t,
+                                        field_layout::kTvEnum>(
       PROTOBUF_TC_PARAM_PASS);
 }
 
@@ -1505,6 +1582,56 @@
       PROTOBUF_TC_PARAM_PASS);
 }
 
+PROTOBUF_NOINLINE const char* TcParser::FastEr8R1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastErR1(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEr8R2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastErR2(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEv8R1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastEvR1(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEv8R2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastEvR2(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEr8P1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastErP1(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEr8P2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastErP2(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEv8P1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastEvP1(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEv8P2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastEvP2(PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastEr16R1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastErR1(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEr16R2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastErR2(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEv16R1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastEvR1(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEv16R2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastEvR2(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEr16P1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastErP1(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEr16P2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastErP2(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEv16P1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastEvP1(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEv16P2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastEvP2(PROTOBUF_TC_PARAM_PASS);
+}
+
 template <typename TagType, uint8_t min>
 PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularEnumSmallRange(
     PROTOBUF_TC_PARAM_DECL) {
@@ -2263,6 +2390,21 @@
     } else if (is_zigzag) {
       tmp = WireFormatLite::ZigZagDecode32(static_cast<uint32_t>(tmp));
     }
+  } else if (rep == field_layout::kRep16Bits) {
+    if (is_validated_enum) {
+      if (!EnumIsValidAux(tmp, xform_val, *table->field_aux(&entry))) {
+        ptr = ptr2;
+        PROTOBUF_MUSTTAIL return MpUnknownEnumFallback(PROTOBUF_TC_PARAM_PASS);
+      }
+    }
+  } else {
+    ABSL_DCHECK_EQ(rep, static_cast<uint16_t>(field_layout::kRep8Bits));
+    if (is_validated_enum) {
+      if (!EnumIsValidAux(tmp, xform_val, *table->field_aux(&entry))) {
+        ptr = ptr2;
+        PROTOBUF_MUSTTAIL return MpUnknownEnumFallback(PROTOBUF_TC_PARAM_PASS);
+      }
+    }
   }
 
   // Mark the field as present:
@@ -2279,9 +2421,15 @@
     RefAt<uint64_t>(base, entry.offset) = tmp;
   } else if (rep == field_layout::kRep32Bits) {
     RefAt<uint32_t>(base, entry.offset) = static_cast<uint32_t>(tmp);
+  } else if (rep == field_layout::kRep16Bits) {
+    RefAt<uint16_t>(base, entry.offset) = static_cast<uint16_t>(tmp);
   } else {
     ABSL_DCHECK_EQ(rep, static_cast<uint16_t>(field_layout::kRep8Bits));
-    RefAt<bool>(base, entry.offset) = static_cast<bool>(tmp);
+    if ((type_card & field_layout::kFmtMask) == field_layout::kFmtEnum) {
+      RefAt<uint8_t>(base, entry.offset) = static_cast<uint8_t>(tmp);
+    } else {
+      RefAt<bool>(base, entry.offset) = static_cast<bool>(tmp);
+    }
   }
 
   PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_NO_DATA_PASS);
@@ -2370,6 +2518,7 @@
             is_split, uint64_t, (is_split ? 0 : field_layout::kTvZigZag)>(
             PROTOBUF_TC_PARAM_PASS);
       }
+    case field_layout::kRep16Bits >> field_layout::kRepShift:
     case field_layout::kRep32Bits >> field_layout::kRepShift:
       switch (xform_val >> field_layout::kTvShift) {
         case 0:
@@ -2391,8 +2540,21 @@
           Unreachable();
       }
     case field_layout::kRep8Bits >> field_layout::kRepShift:
-      PROTOBUF_MUSTTAIL return MpRepeatedVarintT<is_split, bool, 0>(
-          PROTOBUF_TC_PARAM_PASS);
+      switch (xform_val >> field_layout::kTvShift) {
+        case 0:
+          PROTOBUF_MUSTTAIL return MpRepeatedVarintT<is_split, bool, 0>(
+              PROTOBUF_TC_PARAM_PASS);
+        case field_layout::kTvEnum >> field_layout::kTvShift:
+          PROTOBUF_MUSTTAIL return MpRepeatedVarintT<
+              is_split, uint32_t, (is_split ? 0 : field_layout::kTvEnum)>(
+              PROTOBUF_TC_PARAM_PASS);
+        case field_layout::kTvRange >> field_layout::kTvShift:
+          PROTOBUF_MUSTTAIL return MpRepeatedVarintT<
+              is_split, uint32_t, (is_split ? 0 : field_layout::kTvRange)>(
+              PROTOBUF_TC_PARAM_PASS);
+        default:
+          Unreachable();
+      }
 
     default:
       Unreachable();
@@ -2470,6 +2632,7 @@
             is_split, uint64_t, (is_split ? 0 : field_layout::kTvZigZag)>(
             PROTOBUF_TC_PARAM_PASS);
       }
+    case field_layout::kRep16Bits >> field_layout::kRepShift:
     case field_layout::kRep32Bits >> field_layout::kRepShift:
       switch (xform_val >> field_layout::kTvShift) {
         case 0:
@@ -2491,8 +2654,21 @@
           Unreachable();
       }
     case field_layout::kRep8Bits >> field_layout::kRepShift:
-      PROTOBUF_MUSTTAIL return MpPackedVarintT<is_split, bool, 0>(
-          PROTOBUF_TC_PARAM_PASS);
+      switch (xform_val >> field_layout::kTvShift) {
+        case 0:
+          PROTOBUF_MUSTTAIL return MpPackedVarintT<is_split, bool, 0>(
+              PROTOBUF_TC_PARAM_PASS);
+        case field_layout::kTvEnum >> field_layout::kTvShift:
+          PROTOBUF_MUSTTAIL return MpPackedVarintT<
+              is_split, uint32_t, (is_split ? 0 : field_layout::kTvEnum)>(
+              PROTOBUF_TC_PARAM_PASS);
+        case field_layout::kTvRange >> field_layout::kTvShift:
+          PROTOBUF_MUSTTAIL return MpPackedVarintT<
+              is_split, uint32_t, (is_split ? 0 : field_layout::kTvRange)>(
+              PROTOBUF_TC_PARAM_PASS);
+        default:
+          Unreachable();
+      }
 
     default:
       Unreachable();
@@ -3209,6 +3385,12 @@
     case fl::kFkPackedFixed: {
       switch (type_card & ~fl::kFcMask & ~fl::kSplitMask) {
         PROTOBUF_INTERNAL_TYPE_CARD_CASE(Bool);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(Enum8);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(EnumRange8);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(OpenEnum8);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(Enum16);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(EnumRange16);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(OpenEnum16);
         PROTOBUF_INTERNAL_TYPE_CARD_CASE(Fixed32);
         PROTOBUF_INTERNAL_TYPE_CARD_CASE(UInt32);
         PROTOBUF_INTERNAL_TYPE_CARD_CASE(SFixed32);
@@ -3225,6 +3407,12 @@
         PROTOBUF_INTERNAL_TYPE_CARD_CASE(SInt64);
         PROTOBUF_INTERNAL_TYPE_CARD_CASE(Double);
         PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedBool);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedEnum8);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedEnumRange8);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedOpenEnum8);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedEnum16);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedEnumRange16);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedOpenEnum16);
         PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedFixed32);
         PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedUInt32);
         PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedSFixed32);
diff --git a/src/google/protobuf/generated_message_tctable_lite_test.cc b/src/google/protobuf/generated_message_tctable_lite_test.cc
index ad4afdc..8b3c37a 100644
--- a/src/google/protobuf/generated_message_tctable_lite_test.cc
+++ b/src/google/protobuf/generated_message_tctable_lite_test.cc
@@ -134,7 +134,7 @@
   };
   uint8_t serialize_buffer[64];
 
-  for (int size : {8, 32, 64}) {
+  for (int size : {8, 16, 32, 64}) {
     SCOPED_TRACE(size);
     auto next_i = [](uint64_t i) {
       // if i + 1 is a power of two, return that.
@@ -201,6 +201,9 @@
           case 8:
             fn = &TcParser::FastV8S1;
             break;
+          case 16:
+            fn = &TcParser::FastV16S1;
+            break;
           case 32:
             fn = &TcParser::FastV32S1;
             break;
@@ -239,6 +242,13 @@
             EXPECT_EQ(actual_field, static_cast<decltype(actual_field)>(i))  //
                 << " hex: " << absl::StrCat(absl::Hex(actual_field));
           }; break;
+          case 16: {
+            ASSERT_EQ(end_ptr - ptr, serialized.size());
+
+            auto actual_field = ReadAndReset<uint16_t>(&fake_msg[kFieldOffset]);
+            EXPECT_EQ(actual_field, static_cast<decltype(actual_field)>(i))  //
+                << " hex: " << absl::StrCat(absl::Hex(actual_field));
+          }; break;
           case 32: {
             ASSERT_TRUE(end_ptr);
             ASSERT_EQ(end_ptr - ptr, serialized.size());
@@ -1071,6 +1081,179 @@
   (void)msg->ParseFromString(payload);
 }
 
+TEST(TcParserTest, Enum8And16TypeCardToString) {
+  namespace fl = internal::field_layout;
+  EXPECT_EQ(
+      TypeCardToString(static_cast<uint16_t>(fl::kFcOptional) | fl::kEnum8),
+      "::_fl::kFcOptional | ::_fl::kEnum8");
+  EXPECT_EQ(TypeCardToString(static_cast<uint16_t>(fl::kFcOptional) |
+                             fl::kEnumRange8),
+            "::_fl::kFcOptional | ::_fl::kEnumRange8");
+  EXPECT_EQ(
+      TypeCardToString(static_cast<uint16_t>(fl::kFcOptional) | fl::kOpenEnum8),
+      "::_fl::kFcOptional | ::_fl::kOpenEnum8");
+  EXPECT_EQ(
+      TypeCardToString(static_cast<uint16_t>(fl::kFcOptional) | fl::kEnum16),
+      "::_fl::kFcOptional | ::_fl::kEnum16");
+  EXPECT_EQ(TypeCardToString(static_cast<uint16_t>(fl::kFcOptional) |
+                             fl::kEnumRange16),
+            "::_fl::kFcOptional | ::_fl::kEnumRange16");
+  EXPECT_EQ(TypeCardToString(static_cast<uint16_t>(fl::kFcOptional) |
+                             fl::kOpenEnum16),
+            "::_fl::kFcOptional | ::_fl::kOpenEnum16");
+
+  EXPECT_EQ(TypeCardToString(static_cast<uint16_t>(fl::kFcRepeated) |
+                             fl::kPackedEnum8),
+            "::_fl::kFcRepeated | ::_fl::kPackedEnum8");
+  EXPECT_EQ(TypeCardToString(static_cast<uint16_t>(fl::kFcRepeated) |
+                             fl::kPackedEnumRange8),
+            "::_fl::kFcRepeated | ::_fl::kPackedEnumRange8");
+  EXPECT_EQ(TypeCardToString(static_cast<uint16_t>(fl::kFcRepeated) |
+                             fl::kPackedOpenEnum8),
+            "::_fl::kFcRepeated | ::_fl::kPackedOpenEnum8");
+  EXPECT_EQ(TypeCardToString(static_cast<uint16_t>(fl::kFcRepeated) |
+                             fl::kPackedEnum16),
+            "::_fl::kFcRepeated | ::_fl::kPackedEnum16");
+  EXPECT_EQ(TypeCardToString(static_cast<uint16_t>(fl::kFcRepeated) |
+                             fl::kPackedEnumRange16),
+            "::_fl::kFcRepeated | ::_fl::kPackedEnumRange16");
+  EXPECT_EQ(TypeCardToString(static_cast<uint16_t>(fl::kFcRepeated) |
+                             fl::kPackedOpenEnum16),
+            "::_fl::kFcRepeated | ::_fl::kPackedOpenEnum16");
+}
+
+TEST(TcParserTest, FastEnum8And16Parsing) {
+  constexpr uint8_t kHasBitsOffset = 4;
+  constexpr uint8_t kHasBitIndex = 0;
+  constexpr uint8_t kFieldOffset = 24;
+
+  const ClassData class_data(nullptr, nullptr, MessageCreator(), nullptr,
+                             nullptr, nullptr, nullptr,
+                             /*cached_size_offset=*/16, "type_name");
+
+  alignas(16) char fake_msg[64];
+  memset(fake_msg, kDND, sizeof(fake_msg));
+  memset(&fake_msg[kHasBitsOffset], 0, sizeof(uint32_t));
+
+  TcParseTable<1, 1, 2, 0, 2> parse_table = {
+      // header:
+      {
+          kHasBitsOffset,
+          0,
+          1,
+          0,
+          offsetof(decltype(parse_table), field_lookup_table),
+          0xFFFFFFFF - 1,
+          offsetof(decltype(parse_table), field_entries),
+          1,
+          2,
+          offsetof(decltype(parse_table), aux_entries),
+          &class_data,
+          nullptr,
+          &FastParserGaveUp,
+      },
+      // Fast entries:
+      {{
+          {},
+      }},
+      // Field Lookup Table:
+      {{65535, 65535}},
+      // Field Entries:
+      {{
+          {kFieldOffset, kHasBitsOffset + 0, 0, field_layout::kEnum8},
+      }},
+      // Aux Entries:
+      {{
+          {0, 10},  // range 0..10
+          {FieldAuxEnumData{},
+           EnumTraits<proto2_unittest::ForeignEnum>::validation_data()},
+      }},
+  };
+
+  uint8_t serialize_buffer[64];
+  auto serialize_ptr = WireFormatLite::WriteUInt32ToArray(
+      /* field_number= */ 1, 5, serialize_buffer);
+  absl::string_view serialized{
+      reinterpret_cast<char*>(&serialize_buffer[0]),
+      static_cast<size_t>(serialize_ptr - serialize_buffer)};
+
+  // Test FastEr8S1 (range validation for 8-bit enum)
+  {
+    memset(fake_msg, kDND, sizeof(fake_msg));
+    memset(&fake_msg[kHasBitsOffset], 0, sizeof(uint32_t));
+    const char* ptr = nullptr;
+    ParseContext ctx(io::CodedInputStream::GetDefaultRecursionLimit(),
+                     /* aliasing= */ false, &ptr, serialized);
+    TcFieldData data(/*coded_tag=*/8, kHasBitIndex, /*aux_idx=*/0,
+                     kFieldOffset);
+    const char* end_ptr = TcParser::FastEr8S1(
+        reinterpret_cast<MessageLite*>(fake_msg), ptr, &ctx,
+        Xor2SerializedBytes(data, ptr), &parse_table.header, /*hasbits=*/0);
+    ASSERT_EQ(end_ptr - ptr, serialized.size());
+    auto actual_field = ReadAndReset<uint8_t>(&fake_msg[kFieldOffset]);
+    EXPECT_EQ(actual_field, 5);
+    auto hasbits = ReadAndReset<uint32_t>(&fake_msg[kHasBitsOffset]);
+    EXPECT_EQ(hasbits, 1 << kHasBitIndex);
+  }
+
+  // Test FastEv8S1 (function validation for 8-bit enum)
+  {
+    memset(fake_msg, kDND, sizeof(fake_msg));
+    memset(&fake_msg[kHasBitsOffset], 0, sizeof(uint32_t));
+    const char* ptr = nullptr;
+    ParseContext ctx(io::CodedInputStream::GetDefaultRecursionLimit(),
+                     /* aliasing= */ false, &ptr, serialized);
+    TcFieldData data(/*coded_tag=*/8, kHasBitIndex, /*aux_idx=*/1,
+                     kFieldOffset);
+    const char* end_ptr = TcParser::FastEv8S1(
+        reinterpret_cast<MessageLite*>(fake_msg), ptr, &ctx,
+        Xor2SerializedBytes(data, ptr), &parse_table.header, /*hasbits=*/0);
+    ASSERT_EQ(end_ptr - ptr, serialized.size());
+    auto actual_field = ReadAndReset<uint8_t>(&fake_msg[kFieldOffset]);
+    EXPECT_EQ(actual_field, 5);
+    auto hasbits = ReadAndReset<uint32_t>(&fake_msg[kHasBitsOffset]);
+    EXPECT_EQ(hasbits, 1 << kHasBitIndex);
+  }
+
+  // Test FastEr16S1 (range validation for 16-bit enum)
+  {
+    memset(fake_msg, kDND, sizeof(fake_msg));
+    memset(&fake_msg[kHasBitsOffset], 0, sizeof(uint32_t));
+    const char* ptr = nullptr;
+    ParseContext ctx(io::CodedInputStream::GetDefaultRecursionLimit(),
+                     /* aliasing= */ false, &ptr, serialized);
+    TcFieldData data(/*coded_tag=*/8, kHasBitIndex, /*aux_idx=*/0,
+                     kFieldOffset);
+    const char* end_ptr = TcParser::FastEr16S1(
+        reinterpret_cast<MessageLite*>(fake_msg), ptr, &ctx,
+        Xor2SerializedBytes(data, ptr), &parse_table.header, /*hasbits=*/0);
+    ASSERT_EQ(end_ptr - ptr, serialized.size());
+    auto actual_field = ReadAndReset<uint16_t>(&fake_msg[kFieldOffset]);
+    EXPECT_EQ(actual_field, 5);
+    auto hasbits = ReadAndReset<uint32_t>(&fake_msg[kHasBitsOffset]);
+    EXPECT_EQ(hasbits, 1 << kHasBitIndex);
+  }
+
+  // Test FastEv16S1 (function validation for 16-bit enum)
+  {
+    memset(fake_msg, kDND, sizeof(fake_msg));
+    memset(&fake_msg[kHasBitsOffset], 0, sizeof(uint32_t));
+    const char* ptr = nullptr;
+    ParseContext ctx(io::CodedInputStream::GetDefaultRecursionLimit(),
+                     /* aliasing= */ false, &ptr, serialized);
+    TcFieldData data(/*coded_tag=*/8, kHasBitIndex, /*aux_idx=*/1,
+                     kFieldOffset);
+    const char* end_ptr = TcParser::FastEv16S1(
+        reinterpret_cast<MessageLite*>(fake_msg), ptr, &ctx,
+        Xor2SerializedBytes(data, ptr), &parse_table.header, /*hasbits=*/0);
+    ASSERT_EQ(end_ptr - ptr, serialized.size());
+    auto actual_field = ReadAndReset<uint16_t>(&fake_msg[kFieldOffset]);
+    EXPECT_EQ(actual_field, 5);
+    auto hasbits = ReadAndReset<uint32_t>(&fake_msg[kHasBitsOffset]);
+    EXPECT_EQ(hasbits, 1 << kHasBitIndex);
+  }
+}
+
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/json_enumvalue_options.pb.h b/src/google/protobuf/json_enumvalue_options.pb.h
index 2c25bb4..e7edc25 100644
--- a/src/google/protobuf/json_enumvalue_options.pb.h
+++ b/src/google/protobuf/json_enumvalue_options.pb.h
@@ -257,6 +257,7 @@
   friend class ::google::protobuf::Arena::InternalHelper;
   using InternalArenaConstructable_ = void;
   using DestructorSkippable_ = void;
+  // NOLINTBEGIN(google3-readability-class-member-naming,readability-identifier-naming)
   struct Impl_ {
     inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility,
                                     ::google::protobuf::internal::ConstantInitialized) noexcept;
@@ -272,6 +273,7 @@
     ::google::protobuf::internal::ArenaStringPtr string_;
     PROTOBUF_TSAN_DECLARE_MEMBER
   };
+  // NOLINTEND(google3-readability-class-member-naming,readability-identifier-naming)
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fjson_5fenumvalue_5foptions_2eproto;
 };
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index 63b8396..4de91e9 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -1901,6 +1901,11 @@
         << error();
   } else {
     auto cpp_type = field->cpp_type();
+    if (cpp_type == field->CPPTYPE_ENUM &&
+        (std::is_same_v<T, uint8_t> || std::is_same_v<T, int8_t> ||
+         std::is_same_v<T, uint16_t> || std::is_same_v<T, int16_t>)) {
+      return;
+    }
     // Collapse ENUM to INT32 because they are the same through reflection.
     if (cpp_type == field->CPPTYPE_ENUM) cpp_type = field->CPPTYPE_INT32;
     ABSL_DCHECK_EQ(+cpp_type, +internal::GetCppType<T>()) << error();
diff --git a/src/google/protobuf/reflection_visit_field_info.h b/src/google/protobuf/reflection_visit_field_info.h
index c0da446..53e81d1 100644
--- a/src/google/protobuf/reflection_visit_field_info.h
+++ b/src/google/protobuf/reflection_visit_field_info.h
@@ -392,14 +392,7 @@
   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);
-    }
-  }
+  int Get() const { return reflection->GetEnumValue(message, field); }
   void Set(int value) { reflection->SetEnumValue(&message, field, value); }
   void Clear() {
     DynamicFieldInfoHelper<is_oneof>::ClearField(reflection, message, field);
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
index a4850e6..e93f548 100644
--- a/src/google/protobuf/unittest.proto
+++ b/src/google/protobuf/unittest.proto
@@ -2729,3 +2729,69 @@
     TestAllTypes ext = 10;
   }
 }
+
+enum Enum1ByteUnsigned {
+  ENUM1_U_UNSPECIFIED = 0;
+  ENUM1_U_ONE = 1;
+  ENUM1_U_MAX = 200;
+}
+
+enum Enum1ByteSigned {
+  ENUM1_S_UNSPECIFIED = 0;
+  ENUM1_S_MIN = -100;
+  ENUM1_S_MAX = 100;
+}
+
+enum Enum2ByteUnsigned {
+  ENUM2_U_UNSPECIFIED = 0;
+  ENUM2_U_ONE = 1;
+  ENUM2_U_MAX = 1000;
+}
+
+enum Enum2ByteSigned {
+  ENUM2_S_UNSPECIFIED = 0;
+  ENUM2_S_MIN = -1000;
+  ENUM2_S_MAX = 1000;
+}
+
+enum Enum4Byte {
+  ENUM4_UNSPECIFIED = 0;
+  ENUM4_ONE = 1;
+  ENUM4_MAX = 100000;
+}
+
+enum EnumOpen {
+  option features.enum_type = OPEN;
+  ENUM_OPEN_UNSPECIFIED = 0;
+  ENUM_OPEN_ONE = 1;
+}
+
+message TestShrunkenEnumSizes {
+  Enum1ByteUnsigned enum1_u = 1;
+  Enum1ByteSigned enum1_s = 2;
+  Enum2ByteUnsigned enum2_u = 3;
+  Enum2ByteSigned enum2_s = 4;
+  Enum4Byte enum4 = 5;
+  bool flag = 6;
+  int32 small_int = 7;
+}
+
+message TestShrunkenEnumPacking {
+  Enum1ByteUnsigned e1 = 1;
+  Enum1ByteSigned e2 = 2;
+  Enum2ByteUnsigned e3 = 3;
+  bool b1 = 4;
+  bool b2 = 5;
+  bool b3 = 6;
+  bool b4 = 7;
+}
+
+message TestShrunkenEnumOneof {
+  oneof foo {
+    Enum1ByteUnsigned e1_u = 1;
+    Enum1ByteSigned e1_s = 2;
+    Enum2ByteUnsigned e2_u = 3;
+    Enum2ByteSigned e2_s = 4;
+    int32 bar = 5;
+  }
+}